fivetran-connector-sdk 1.7.5__tar.gz → 1.8.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.
- {fivetran_connector_sdk-1.7.5 → fivetran_connector_sdk-1.8.0}/PKG-INFO +1 -1
- {fivetran_connector_sdk-1.7.5 → fivetran_connector_sdk-1.8.0}/src/fivetran_connector_sdk/__init__.py +11 -2
- {fivetran_connector_sdk-1.7.5 → fivetran_connector_sdk-1.8.0}/src/fivetran_connector_sdk/connector_helper.py +39 -42
- {fivetran_connector_sdk-1.7.5 → fivetran_connector_sdk-1.8.0}/src/fivetran_connector_sdk/constants.py +7 -1
- {fivetran_connector_sdk-1.7.5 → fivetran_connector_sdk-1.8.0}/src/fivetran_connector_sdk/operations.py +115 -21
- {fivetran_connector_sdk-1.7.5 → fivetran_connector_sdk-1.8.0}/src/fivetran_connector_sdk/protos/connector_sdk_pb2.py +14 -12
- {fivetran_connector_sdk-1.7.5 → fivetran_connector_sdk-1.8.0}/src/fivetran_connector_sdk/protos/connector_sdk_pb2.pyi +10 -2
- {fivetran_connector_sdk-1.7.5 → fivetran_connector_sdk-1.8.0}/src/fivetran_connector_sdk.egg-info/PKG-INFO +1 -1
- {fivetran_connector_sdk-1.7.5 → fivetran_connector_sdk-1.8.0}/README.md +0 -0
- {fivetran_connector_sdk-1.7.5 → fivetran_connector_sdk-1.8.0}/pyproject.toml +0 -0
- {fivetran_connector_sdk-1.7.5 → fivetran_connector_sdk-1.8.0}/setup.cfg +0 -0
- {fivetran_connector_sdk-1.7.5 → fivetran_connector_sdk-1.8.0}/src/fivetran_connector_sdk/helpers.py +0 -0
- {fivetran_connector_sdk-1.7.5 → fivetran_connector_sdk-1.8.0}/src/fivetran_connector_sdk/logger.py +0 -0
- {fivetran_connector_sdk-1.7.5 → fivetran_connector_sdk-1.8.0}/src/fivetran_connector_sdk/protos/__init__.py +0 -0
- {fivetran_connector_sdk-1.7.5 → fivetran_connector_sdk-1.8.0}/src/fivetran_connector_sdk/protos/common_pb2.py +0 -0
- {fivetran_connector_sdk-1.7.5 → fivetran_connector_sdk-1.8.0}/src/fivetran_connector_sdk/protos/common_pb2.pyi +0 -0
- {fivetran_connector_sdk-1.7.5 → fivetran_connector_sdk-1.8.0}/src/fivetran_connector_sdk/protos/common_pb2_grpc.py +0 -0
- {fivetran_connector_sdk-1.7.5 → fivetran_connector_sdk-1.8.0}/src/fivetran_connector_sdk/protos/connector_sdk_pb2_grpc.py +0 -0
- {fivetran_connector_sdk-1.7.5 → fivetran_connector_sdk-1.8.0}/src/fivetran_connector_sdk.egg-info/SOURCES.txt +0 -0
- {fivetran_connector_sdk-1.7.5 → fivetran_connector_sdk-1.8.0}/src/fivetran_connector_sdk.egg-info/dependency_links.txt +0 -0
- {fivetran_connector_sdk-1.7.5 → fivetran_connector_sdk-1.8.0}/src/fivetran_connector_sdk.egg-info/entry_points.txt +0 -0
- {fivetran_connector_sdk-1.7.5 → fivetran_connector_sdk-1.8.0}/src/fivetran_connector_sdk.egg-info/requires.txt +0 -0
- {fivetran_connector_sdk-1.7.5 → fivetran_connector_sdk-1.8.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
|
+
Version: 1.8.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
|
{fivetran_connector_sdk-1.7.5 → fivetran_connector_sdk-1.8.0}/src/fivetran_connector_sdk/__init__.py
RENAMED
@@ -42,7 +42,7 @@ from fivetran_connector_sdk.connector_helper import (
|
|
42
42
|
|
43
43
|
# Version format: <major_version>.<minor_version>.<patch_version>
|
44
44
|
# (where Major Version = 1 for GA, Minor Version is incremental MM from Jan 25 onwards, Patch Version is incremental within a month)
|
45
|
-
__version__ = "1.
|
45
|
+
__version__ = "1.8.0"
|
46
46
|
TESTER_VERSION = TESTER_VER
|
47
47
|
MAX_MESSAGE_LENGTH = 32 * 1024 * 1024 # 32MB
|
48
48
|
|
@@ -396,7 +396,16 @@ class Connector(connector_sdk_pb2_grpc.SourceConnectorServicer):
|
|
396
396
|
thread = threading.Thread(target=run_update)
|
397
397
|
thread.start()
|
398
398
|
|
399
|
-
yield
|
399
|
+
# consumer - yield the operations in the operation_stream.
|
400
|
+
for response in Operations.operation_stream:
|
401
|
+
# checkpoint call always returns list of responses.
|
402
|
+
if isinstance(response, list):
|
403
|
+
for res in response:
|
404
|
+
yield res
|
405
|
+
# checkpoint call blocks the queue (see _OperationStream.add method). unblock the queue after yielding all responses.
|
406
|
+
Operations.operation_stream.unblock()
|
407
|
+
else:
|
408
|
+
yield response
|
400
409
|
|
401
410
|
thread.join()
|
402
411
|
|
@@ -57,27 +57,22 @@ def get_destination_group(args):
|
|
57
57
|
ft_group = get_input_from_cli("Provide the destination name (as displayed in your dashboard destination list)", env_destination_name)
|
58
58
|
return ft_group
|
59
59
|
|
60
|
-
def get_connection_name(args):
|
60
|
+
def get_connection_name(args, retrying=0):
|
61
61
|
ft_connection = args.connection if args.connection else None
|
62
62
|
env_connection_name = os.getenv('FIVETRAN_CONNECTION_NAME', None)
|
63
63
|
if not ft_connection:
|
64
|
-
|
65
|
-
ft_connection = get_input_from_cli("Provide the connection name", env_connection_name)
|
66
|
-
if not is_connection_name_valid(ft_connection):
|
67
|
-
if retrying==MAX_RETRIES-1:
|
68
|
-
sys.exit(1)
|
69
|
-
else:
|
70
|
-
print_library_log(f"Connection name: {ft_connection} is invalid!\n The connection name should start with an "
|
71
|
-
f"underscore or a lowercase letter (a-z), followed by any combination of underscores, lowercase "
|
72
|
-
f"letters, or digits (0-9). Uppercase characters are not allowed.", Logging.Level.SEVERE)
|
73
|
-
print_library_log("Please retry...", Logging.Level.INFO)
|
74
|
-
else:
|
75
|
-
break
|
64
|
+
ft_connection = get_input_from_cli("Provide the connection name", env_connection_name)
|
76
65
|
if not is_connection_name_valid(ft_connection):
|
77
|
-
print_library_log(
|
78
|
-
|
79
|
-
|
80
|
-
|
66
|
+
print_library_log(
|
67
|
+
f"Connection name: {ft_connection} is invalid!\n The connection name should start with an "
|
68
|
+
f"underscore or a lowercase letter (a-z), followed by any combination of underscores, lowercase "
|
69
|
+
f"letters, or digits (0-9). Uppercase characters are not allowed.", Logging.Level.SEVERE)
|
70
|
+
args.connection = None
|
71
|
+
if retrying >= MAX_RETRIES or args.force:
|
72
|
+
sys.exit(1)
|
73
|
+
else:
|
74
|
+
print_library_log("Please retry...", Logging.Level.INFO)
|
75
|
+
return get_connection_name(args, retrying + 1)
|
81
76
|
return ft_connection
|
82
77
|
|
83
78
|
def get_api_key(args):
|
@@ -113,32 +108,36 @@ def get_state(args):
|
|
113
108
|
state = validate_and_load_state(args, state)
|
114
109
|
return state
|
115
110
|
|
116
|
-
def get_configuration(args):
|
111
|
+
def get_configuration(args, retrying = 0):
|
117
112
|
configuration = args.configuration if args.configuration else None
|
118
113
|
env_configuration = os.getenv('FIVETRAN_CONFIGURATION', None)
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
114
|
+
try:
|
115
|
+
if not configuration and not args.force and args.command.lower() == "deploy":
|
116
|
+
confirm = 'y'
|
117
|
+
if not retrying:
|
118
|
+
json_filepath = os.path.join(args.project_path, "configuration.json")
|
119
|
+
if os.path.exists(json_filepath):
|
120
|
+
print_library_log("configuration.json file detected in the project, "
|
121
|
+
"but no configuration input provided via the command line", Logging.Level.WARNING)
|
122
|
+
env_configuration = env_configuration if env_configuration else "configuration.json"
|
123
|
+
confirm = input(f"Does this debug run/deploy need configuration (y/N):")
|
124
|
+
if confirm.lower()=='y':
|
125
|
+
configuration = get_input_from_cli("Provide the configuration file path", env_configuration)
|
126
|
+
config_values = validate_and_load_configuration(args.project_path, configuration)
|
127
|
+
return config_values, configuration
|
128
|
+
else:
|
129
|
+
print_library_log("No input required for configuration. Continuing without configuration.", Logging.Level.INFO)
|
130
|
+
return {}, None
|
131
|
+
config_values = validate_and_load_configuration(args.project_path, configuration)
|
132
|
+
return config_values, configuration
|
133
|
+
except ValueError as e:
|
134
|
+
args.configuration = None
|
135
|
+
if retrying >= MAX_RETRIES or args.force:
|
136
|
+
print_library_log(f"{e}. Invalid Configuration, Exiting..", Logging.Level.WARNING)
|
137
|
+
sys.exit(1)
|
138
138
|
else:
|
139
|
-
print_library_log("
|
140
|
-
|
141
|
-
return config_values, configuration
|
139
|
+
print_library_log(f"{e}. Please retry..", Logging.Level.INFO)
|
140
|
+
return get_configuration(args, retrying + 1)
|
142
141
|
|
143
142
|
|
144
143
|
def check_newer_version(version: str):
|
@@ -989,8 +988,6 @@ def process_data_type(column, type):
|
|
989
988
|
column.type = common_pb2.DataType.FLOAT
|
990
989
|
elif type.upper() == "DOUBLE":
|
991
990
|
column.type = common_pb2.DataType.DOUBLE
|
992
|
-
elif type.upper() == "NAIVE_TIME":
|
993
|
-
column.type = common_pb2.DataType.NAIVE_TIME
|
994
991
|
elif type.upper() == "NAIVE_DATE":
|
995
992
|
column.type = common_pb2.DataType.NAIVE_DATE
|
996
993
|
elif type.upper() == "NAIVE_DATETIME":
|
@@ -1,6 +1,7 @@
|
|
1
|
+
import os
|
1
2
|
import re
|
2
3
|
|
3
|
-
TESTER_VER = "2.25.
|
4
|
+
TESTER_VER = "2.25.0806.001"
|
4
5
|
|
5
6
|
WIN_OS = "windows"
|
6
7
|
ARM_64 = "arm64"
|
@@ -34,11 +35,16 @@ OUTPUT_FILES_DIR = "files"
|
|
34
35
|
REQUIREMENTS_TXT = "requirements.txt"
|
35
36
|
PYPI_PACKAGE_DETAILS_URL = "https://pypi.org/pypi/fivetran_connector_sdk/json"
|
36
37
|
ONE_DAY_IN_SEC = 24 * 60 * 60
|
38
|
+
CHECKPOINT_OP_TIMEOUT_IN_SEC = 30 # seconds
|
37
39
|
MAX_RETRIES = 3
|
38
40
|
LOGGING_PREFIX = "Fivetran-Connector-SDK"
|
39
41
|
LOGGING_DELIMITER = ": "
|
40
42
|
VIRTUAL_ENV_CONFIG = "pyvenv.cfg"
|
41
43
|
ROOT_FILENAME = "connector.py"
|
44
|
+
MAX_RECORDS_IN_BATCH = 100
|
45
|
+
MAX_BATCH_SIZE_IN_BYTES = 100000 # 100 KB
|
46
|
+
# The increased queue size shall be rolled out as Feature flag
|
47
|
+
QUEUE_SIZE = int(os.environ.get("QUEUE_SIZE", 1))
|
42
48
|
|
43
49
|
# Compile patterns used in the implementation
|
44
50
|
WORD_DASH_DOT_PATTERN = re.compile(r'^[\w.-]*$')
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import json
|
2
|
-
import os
|
3
2
|
import sys
|
4
3
|
import queue
|
4
|
+
import threading
|
5
5
|
|
6
6
|
from datetime import datetime
|
7
7
|
from google.protobuf import timestamp_pb2
|
@@ -9,6 +9,10 @@ from google.protobuf import timestamp_pb2
|
|
9
9
|
from fivetran_connector_sdk.constants import (
|
10
10
|
JAVA_LONG_MAX_VALUE,
|
11
11
|
TABLES,
|
12
|
+
MAX_RECORDS_IN_BATCH,
|
13
|
+
MAX_BATCH_SIZE_IN_BYTES,
|
14
|
+
QUEUE_SIZE,
|
15
|
+
CHECKPOINT_OP_TIMEOUT_IN_SEC
|
12
16
|
)
|
13
17
|
from fivetran_connector_sdk.helpers import (
|
14
18
|
get_renamed_table_name,
|
@@ -38,8 +42,15 @@ class _OperationStream:
|
|
38
42
|
"""
|
39
43
|
Initializes the operation stream with a queue and a sentinel object.
|
40
44
|
"""
|
41
|
-
self._queue = queue.Queue(maxsize=
|
45
|
+
self._queue = queue.Queue(maxsize=QUEUE_SIZE)
|
42
46
|
self._sentinel = object()
|
47
|
+
self._is_done = False
|
48
|
+
self._buffer = []
|
49
|
+
self._buffer_record_count = 0
|
50
|
+
self._buffer_size_bytes = 0
|
51
|
+
self._checkpoint_lock = threading.Lock()
|
52
|
+
self._checkpoint_flush_signal = threading.Event()
|
53
|
+
self._checkpoint_flush_signal.set()
|
43
54
|
|
44
55
|
def __iter__(self):
|
45
56
|
"""
|
@@ -47,14 +58,38 @@ class _OperationStream:
|
|
47
58
|
"""
|
48
59
|
return self
|
49
60
|
|
50
|
-
def add(self,
|
61
|
+
def add(self, operation):
|
51
62
|
"""
|
52
|
-
Adds an
|
63
|
+
Adds an operation to the stream. Guarantees that operations within a single thread are processed in the order.
|
64
|
+
|
65
|
+
In multithreaded environment if a thread initiates a checkpoint, it's producer is blocked until the
|
66
|
+
checkpoint flush is complete. This block is localized, other threads
|
67
|
+
remain unblocked and can continue to perform other operations
|
68
|
+
(such as upserts, updates, deletes), but they are prevented from initiating a new checkpoint
|
69
|
+
until the existing one is finished.
|
53
70
|
|
54
71
|
Args:
|
55
|
-
|
72
|
+
operation (object): The data item to add to the stream.
|
73
|
+
"""
|
74
|
+
if isinstance(operation, connector_sdk_pb2.Checkpoint):
|
75
|
+
# lock to ensure checkpoint operations are processed one at a time
|
76
|
+
with self._checkpoint_lock:
|
77
|
+
# clear the signal to indicate checkpoint operation is being processed.
|
78
|
+
self._checkpoint_flush_signal.clear()
|
79
|
+
self._queue.put(operation)
|
80
|
+
# wait until the consumer flushes the buffer and sets the flag.
|
81
|
+
if not self._checkpoint_flush_signal.wait(CHECKPOINT_OP_TIMEOUT_IN_SEC):
|
82
|
+
raise TimeoutError(
|
83
|
+
"Checkpoint flush timed out. Consumer may have failed to process checkpoint."
|
84
|
+
)
|
85
|
+
else:
|
86
|
+
self._queue.put(operation)
|
87
|
+
|
88
|
+
def unblock(self):
|
56
89
|
"""
|
57
|
-
|
90
|
+
Unblocks the queue, called by consumer after the checkpoint flush is completed.
|
91
|
+
"""
|
92
|
+
self._checkpoint_flush_signal.set()
|
58
93
|
|
59
94
|
def mark_done(self):
|
60
95
|
"""
|
@@ -72,10 +107,76 @@ class _OperationStream:
|
|
72
107
|
Raises:
|
73
108
|
StopIteration: If the sentinel object is encountered.
|
74
109
|
"""
|
75
|
-
|
76
|
-
if
|
110
|
+
# If stream is completed and buffer is empty, raise StopIteration. Else flush the buffer.
|
111
|
+
if self._is_done and not self._buffer:
|
77
112
|
raise StopIteration
|
78
|
-
|
113
|
+
|
114
|
+
if self._is_done:
|
115
|
+
return self._flush_buffer()
|
116
|
+
|
117
|
+
return self._build_next_batch()
|
118
|
+
|
119
|
+
def _build_next_batch(self):
|
120
|
+
"""
|
121
|
+
Core logic to build the batch. The loop continues until the buffer is full,
|
122
|
+
but can be interrupted by a checkpoint or a sentinel from the producer.
|
123
|
+
|
124
|
+
Returns:
|
125
|
+
connector_sdk_pb2.UpdateResponse or list[connector_sdk_pb2.UpdateResponse]: Either a single response
|
126
|
+
containing records or checkpoint, or a list of responses when flushing data with a checkpoint.
|
127
|
+
|
128
|
+
"""
|
129
|
+
while self._buffer_record_count < MAX_RECORDS_IN_BATCH and self._buffer_size_bytes < MAX_BATCH_SIZE_IN_BYTES:
|
130
|
+
operation = self._queue.get()
|
131
|
+
|
132
|
+
# Case 1: If operation is sentinel, mark the stream as done, flush the buffer.
|
133
|
+
if operation is self._sentinel:
|
134
|
+
self._is_done = True
|
135
|
+
if self._buffer:
|
136
|
+
return self._flush_buffer()
|
137
|
+
else:
|
138
|
+
raise StopIteration
|
139
|
+
|
140
|
+
# Case 2: if operation is a Checkpoint, flush the buffer and send the checkpoint.
|
141
|
+
elif isinstance(operation, connector_sdk_pb2.Checkpoint):
|
142
|
+
return self._flush_buffer_on_checkpoint(operation)
|
143
|
+
|
144
|
+
# it is record, buffer it to flush in batches
|
145
|
+
self._buffer_record_count += 1
|
146
|
+
self._buffer_size_bytes += len(operation.SerializeToString())
|
147
|
+
self._buffer.append(operation)
|
148
|
+
|
149
|
+
# Case 3: If buffer size limit is reached, flush the buffer and return the response.
|
150
|
+
return self._flush_buffer()
|
151
|
+
|
152
|
+
def _flush_buffer_on_checkpoint(self, checkpoint: connector_sdk_pb2.Checkpoint):
|
153
|
+
"""
|
154
|
+
Creates the responses containing the checkpoint and buffered records.
|
155
|
+
|
156
|
+
Args:
|
157
|
+
checkpoint (object): Checkpoint operation to be added to the response.
|
158
|
+
"""
|
159
|
+
responses = []
|
160
|
+
|
161
|
+
if self._buffer:
|
162
|
+
responses.append(self._flush_buffer())
|
163
|
+
|
164
|
+
responses.append(connector_sdk_pb2.UpdateResponse(checkpoint=checkpoint))
|
165
|
+
return responses
|
166
|
+
|
167
|
+
def _flush_buffer(self):
|
168
|
+
"""
|
169
|
+
Flushes the current buffer and returns a response containing the buffered records.
|
170
|
+
|
171
|
+
Returns:
|
172
|
+
connector_sdk_pb2.UpdateResponse: A response containing the buffered records.
|
173
|
+
"""
|
174
|
+
batch_to_flush = self._buffer
|
175
|
+
self._buffer = []
|
176
|
+
self._buffer_record_count = 0
|
177
|
+
self._buffer_size_bytes = 0
|
178
|
+
return connector_sdk_pb2.UpdateResponse(records=connector_sdk_pb2.Records(records=batch_to_flush))
|
179
|
+
|
79
180
|
|
80
181
|
_LOG_DATA_TYPE_INFERENCE = {
|
81
182
|
"boolean": True,
|
@@ -114,10 +215,8 @@ class Operations:
|
|
114
215
|
type=common_pb2.RecordType.UPSERT,
|
115
216
|
data=mapped_data
|
116
217
|
)
|
117
|
-
update_response = connector_sdk_pb2.UpdateResponse(record=record)
|
118
|
-
|
119
|
-
Operations.operation_stream.add(update_response)
|
120
218
|
|
219
|
+
Operations.operation_stream.add(record)
|
121
220
|
|
122
221
|
@staticmethod
|
123
222
|
def update(table: str, modified: dict):
|
@@ -140,9 +239,7 @@ class Operations:
|
|
140
239
|
data=mapped_data
|
141
240
|
)
|
142
241
|
|
143
|
-
|
144
|
-
|
145
|
-
Operations.operation_stream.add(update_response)
|
242
|
+
Operations.operation_stream.add(record)
|
146
243
|
|
147
244
|
@staticmethod
|
148
245
|
def delete(table: str, keys: dict):
|
@@ -165,9 +262,7 @@ class Operations:
|
|
165
262
|
data=mapped_data
|
166
263
|
)
|
167
264
|
|
168
|
-
|
169
|
-
|
170
|
-
Operations.operation_stream.add(update_response)
|
265
|
+
Operations.operation_stream.add(record)
|
171
266
|
|
172
267
|
@staticmethod
|
173
268
|
def checkpoint(state: dict):
|
@@ -190,9 +285,9 @@ class Operations:
|
|
190
285
|
Returns:
|
191
286
|
connector_sdk_pb2.UpdateResponse: The checkpoint response.
|
192
287
|
"""
|
193
|
-
|
288
|
+
checkpoint = connector_sdk_pb2.Checkpoint(state_json=json.dumps(state))
|
194
289
|
|
195
|
-
Operations.operation_stream.add(
|
290
|
+
Operations.operation_stream.add(checkpoint)
|
196
291
|
|
197
292
|
def _get_columns(table: str) -> dict:
|
198
293
|
"""Retrieves the columns for the specified table.
|
@@ -334,4 +429,3 @@ def _yield_check(stack):
|
|
334
429
|
# This should never happen
|
335
430
|
raise RuntimeError(
|
336
431
|
f"The '{called_method}' function is missing in the connector calling code '{calling_code}'. Please ensure that the '{called_method}' function is properly defined in your code to proceed. Reference: https://fivetran.com/docs/connectors/connector-sdk/technical-reference#technicaldetailsmethods")
|
337
|
-
|
@@ -26,7 +26,7 @@ _sym_db = _symbol_database.Default()
|
|
26
26
|
from fivetran_connector_sdk import common_pb2 as common__pb2
|
27
27
|
|
28
28
|
|
29
|
-
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x13\x63onnector_sdk.proto\x12\x0f\x66ivetran_sdk.v2\x1a\x0c\x63ommon.proto\"\x8f\x01\n\rSchemaRequest\x12H\n\rconfiguration\x18\x01 \x03(\x0b\x32\x31.fivetran_sdk.v2.SchemaRequest.ConfigurationEntry\x1a\x34\n\x12\x43onfigurationEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xf1\x01\n\x0eSchemaResponse\x12\'\n\x1dschema_response_not_supported\x18\x01 \x01(\x08H\x00\x12\x32\n\x0bwith_schema\x18\x02 \x01(\x0b\x32\x1b.fivetran_sdk.v2.SchemaListH\x00\x12\x34\n\x0ewithout_schema\x18\x03 \x01(\x0b\x32\x1a.fivetran_sdk.v2.TableListH\x00\x12$\n\x17selection_not_supported\x18\x04 \x01(\x08H\x01\x88\x01\x01\x42\n\n\x08responseB\x1a\n\x18_selection_not_supported\"\xf9\x01\n\rUpdateRequest\x12H\n\rconfiguration\x18\x01 \x03(\x0b\x32\x31.fivetran_sdk.v2.UpdateRequest.ConfigurationEntry\x12\x32\n\tselection\x18\x02 \x01(\x0b\x32\x1a.fivetran_sdk.v2.SelectionH\x00\x88\x01\x01\x12\x17\n\nstate_json\x18\x03 \x01(\tH\x01\x88\x01\x01\x1a\x34\n\x12\x43onfigurationEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x0c\n\n_selectionB\r\n\x0b_state_json\"\x91\x01\n\tSelection\x12=\n\x0ewithout_schema\x18\x01 \x01(\x0b\x32#.fivetran_sdk.v2.TablesWithNoSchemaH\x00\x12\x38\n\x0bwith_schema\x18\x02 \x01(\x0b\x32!.fivetran_sdk.v2.TablesWithSchemaH\x00\x42\x0b\n\tselection\"a\n\x12TablesWithNoSchema\x12/\n\x06tables\x18\x01 \x03(\x0b\x32\x1f.fivetran_sdk.v2.TableSelection\x12\x1a\n\x12include_new_tables\x18\x02 \x01(\x08\"b\n\x10TablesWithSchema\x12\x31\n\x07schemas\x18\x01 \x03(\x0b\x32 .fivetran_sdk.v2.SchemaSelection\x12\x1b\n\x13include_new_schemas\x18\x02 \x01(\x08\"\x85\x01\n\x0fSchemaSelection\x12\x10\n\x08included\x18\x01 \x01(\x08\x12\x13\n\x0bschema_name\x18\x02 \x01(\t\x12/\n\x06tables\x18\x03 \x03(\x0b\x32\x1f.fivetran_sdk.v2.TableSelection\x12\x1a\n\x12include_new_tables\x18\x04 \x01(\x08\"\xc2\x01\n\x0eTableSelection\x12\x10\n\x08included\x18\x01 \x01(\x08\x12\x12\n\ntable_name\x18\x02 \x01(\t\x12=\n\x07\x63olumns\x18\x03 \x03(\x0b\x32,.fivetran_sdk.v2.TableSelection.ColumnsEntry\x12\x1b\n\x13include_new_columns\x18\x04 \x01(\x08\x1a.\n\x0c\x43olumnsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x08:\x02\x38\x01\"\
|
29
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x13\x63onnector_sdk.proto\x12\x0f\x66ivetran_sdk.v2\x1a\x0c\x63ommon.proto\"\x8f\x01\n\rSchemaRequest\x12H\n\rconfiguration\x18\x01 \x03(\x0b\x32\x31.fivetran_sdk.v2.SchemaRequest.ConfigurationEntry\x1a\x34\n\x12\x43onfigurationEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xf1\x01\n\x0eSchemaResponse\x12\'\n\x1dschema_response_not_supported\x18\x01 \x01(\x08H\x00\x12\x32\n\x0bwith_schema\x18\x02 \x01(\x0b\x32\x1b.fivetran_sdk.v2.SchemaListH\x00\x12\x34\n\x0ewithout_schema\x18\x03 \x01(\x0b\x32\x1a.fivetran_sdk.v2.TableListH\x00\x12$\n\x17selection_not_supported\x18\x04 \x01(\x08H\x01\x88\x01\x01\x42\n\n\x08responseB\x1a\n\x18_selection_not_supported\"\xf9\x01\n\rUpdateRequest\x12H\n\rconfiguration\x18\x01 \x03(\x0b\x32\x31.fivetran_sdk.v2.UpdateRequest.ConfigurationEntry\x12\x32\n\tselection\x18\x02 \x01(\x0b\x32\x1a.fivetran_sdk.v2.SelectionH\x00\x88\x01\x01\x12\x17\n\nstate_json\x18\x03 \x01(\tH\x01\x88\x01\x01\x1a\x34\n\x12\x43onfigurationEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x0c\n\n_selectionB\r\n\x0b_state_json\"\x91\x01\n\tSelection\x12=\n\x0ewithout_schema\x18\x01 \x01(\x0b\x32#.fivetran_sdk.v2.TablesWithNoSchemaH\x00\x12\x38\n\x0bwith_schema\x18\x02 \x01(\x0b\x32!.fivetran_sdk.v2.TablesWithSchemaH\x00\x42\x0b\n\tselection\"a\n\x12TablesWithNoSchema\x12/\n\x06tables\x18\x01 \x03(\x0b\x32\x1f.fivetran_sdk.v2.TableSelection\x12\x1a\n\x12include_new_tables\x18\x02 \x01(\x08\"b\n\x10TablesWithSchema\x12\x31\n\x07schemas\x18\x01 \x03(\x0b\x32 .fivetran_sdk.v2.SchemaSelection\x12\x1b\n\x13include_new_schemas\x18\x02 \x01(\x08\"\x85\x01\n\x0fSchemaSelection\x12\x10\n\x08included\x18\x01 \x01(\x08\x12\x13\n\x0bschema_name\x18\x02 \x01(\t\x12/\n\x06tables\x18\x03 \x03(\x0b\x32\x1f.fivetran_sdk.v2.TableSelection\x12\x1a\n\x12include_new_tables\x18\x04 \x01(\x08\"\xc2\x01\n\x0eTableSelection\x12\x10\n\x08included\x18\x01 \x01(\x08\x12\x12\n\ntable_name\x18\x02 \x01(\t\x12=\n\x07\x63olumns\x18\x03 \x03(\x0b\x32,.fivetran_sdk.v2.TableSelection.ColumnsEntry\x12\x1b\n\x13include_new_columns\x18\x04 \x01(\x08\x1a.\n\x0c\x43olumnsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x08:\x02\x38\x01\"\xb4\x02\n\x0eUpdateResponse\x12)\n\x06record\x18\x01 \x01(\x0b\x32\x17.fivetran_sdk.v2.RecordH\x00\x12\x36\n\rschema_change\x18\x02 \x01(\x0b\x32\x1d.fivetran_sdk.v2.SchemaChangeH\x00\x12\x31\n\ncheckpoint\x18\x03 \x01(\x0b\x32\x1b.fivetran_sdk.v2.CheckpointH\x00\x12+\n\x07warning\x18\x04 \x01(\x0b\x32\x18.fivetran_sdk.v2.WarningH\x00\x12%\n\x04task\x18\x05 \x01(\x0b\x32\x15.fivetran_sdk.v2.TaskH\x00\x12+\n\x07records\x18\x06 \x01(\x0b\x32\x18.fivetran_sdk.v2.RecordsH\x00\x42\x0b\n\toperation\"\x82\x01\n\x0cSchemaChange\x12\x32\n\x0bwith_schema\x18\x01 \x01(\x0b\x32\x1b.fivetran_sdk.v2.SchemaListH\x00\x12\x34\n\x0ewithout_schema\x18\x02 \x01(\x0b\x32\x1a.fivetran_sdk.v2.TableListH\x00\x42\x08\n\x06\x63hange\"3\n\x07Records\x12(\n\x07records\x18\x01 \x03(\x0b\x32\x17.fivetran_sdk.v2.Record\"\xeb\x01\n\x06Record\x12\x18\n\x0bschema_name\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x12\n\ntable_name\x18\x02 \x01(\t\x12)\n\x04type\x18\x03 \x01(\x0e\x32\x1b.fivetran_sdk.v2.RecordType\x12/\n\x04\x64\x61ta\x18\x04 \x03(\x0b\x32!.fivetran_sdk.v2.Record.DataEntry\x1aG\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12)\n\x05value\x18\x02 \x01(\x0b\x32\x1a.fivetran_sdk.v2.ValueType:\x02\x38\x01\x42\x0e\n\x0c_schema_name\" \n\nCheckpoint\x12\x12\n\nstate_json\x18\x01 \x01(\t2\xe2\x02\n\x0fSourceConnector\x12l\n\x11\x43onfigurationForm\x12).fivetran_sdk.v2.ConfigurationFormRequest\x1a*.fivetran_sdk.v2.ConfigurationFormResponse\"\x00\x12\x45\n\x04Test\x12\x1c.fivetran_sdk.v2.TestRequest\x1a\x1d.fivetran_sdk.v2.TestResponse\"\x00\x12K\n\x06Schema\x12\x1e.fivetran_sdk.v2.SchemaRequest\x1a\x1f.fivetran_sdk.v2.SchemaResponse\"\x00\x12M\n\x06Update\x12\x1e.fivetran_sdk.v2.UpdateRequest\x1a\x1f.fivetran_sdk.v2.UpdateResponse\"\x00\x30\x01\x42\"H\x01P\x01Z\x1c\x66ivetran.com/fivetran_sdk_v2b\x06proto3')
|
30
30
|
|
31
31
|
_globals = globals()
|
32
32
|
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
@@ -65,15 +65,17 @@ if not _descriptor._USE_C_DESCRIPTORS:
|
|
65
65
|
_globals['_TABLESELECTION_COLUMNSENTRY']._serialized_start=1328
|
66
66
|
_globals['_TABLESELECTION_COLUMNSENTRY']._serialized_end=1374
|
67
67
|
_globals['_UPDATERESPONSE']._serialized_start=1377
|
68
|
-
_globals['_UPDATERESPONSE']._serialized_end=
|
69
|
-
_globals['_SCHEMACHANGE']._serialized_start=
|
70
|
-
_globals['_SCHEMACHANGE']._serialized_end=
|
71
|
-
_globals['
|
72
|
-
_globals['
|
73
|
-
_globals['
|
74
|
-
_globals['
|
75
|
-
_globals['
|
76
|
-
_globals['
|
77
|
-
_globals['
|
78
|
-
_globals['
|
68
|
+
_globals['_UPDATERESPONSE']._serialized_end=1685
|
69
|
+
_globals['_SCHEMACHANGE']._serialized_start=1688
|
70
|
+
_globals['_SCHEMACHANGE']._serialized_end=1818
|
71
|
+
_globals['_RECORDS']._serialized_start=1820
|
72
|
+
_globals['_RECORDS']._serialized_end=1871
|
73
|
+
_globals['_RECORD']._serialized_start=1874
|
74
|
+
_globals['_RECORD']._serialized_end=2109
|
75
|
+
_globals['_RECORD_DATAENTRY']._serialized_start=2022
|
76
|
+
_globals['_RECORD_DATAENTRY']._serialized_end=2093
|
77
|
+
_globals['_CHECKPOINT']._serialized_start=2111
|
78
|
+
_globals['_CHECKPOINT']._serialized_end=2143
|
79
|
+
_globals['_SOURCECONNECTOR']._serialized_start=2146
|
80
|
+
_globals['_SOURCECONNECTOR']._serialized_end=2500
|
79
81
|
# @@protoc_insertion_point(module_scope)
|
@@ -104,18 +104,20 @@ class TableSelection(_message.Message):
|
|
104
104
|
def __init__(self, included: bool = ..., table_name: _Optional[str] = ..., columns: _Optional[_Mapping[str, bool]] = ..., include_new_columns: bool = ...) -> None: ...
|
105
105
|
|
106
106
|
class UpdateResponse(_message.Message):
|
107
|
-
__slots__ = ("record", "schema_change", "checkpoint", "warning", "task")
|
107
|
+
__slots__ = ("record", "schema_change", "checkpoint", "warning", "task", "records")
|
108
108
|
RECORD_FIELD_NUMBER: _ClassVar[int]
|
109
109
|
SCHEMA_CHANGE_FIELD_NUMBER: _ClassVar[int]
|
110
110
|
CHECKPOINT_FIELD_NUMBER: _ClassVar[int]
|
111
111
|
WARNING_FIELD_NUMBER: _ClassVar[int]
|
112
112
|
TASK_FIELD_NUMBER: _ClassVar[int]
|
113
|
+
RECORDS_FIELD_NUMBER: _ClassVar[int]
|
113
114
|
record: Record
|
114
115
|
schema_change: SchemaChange
|
115
116
|
checkpoint: Checkpoint
|
116
117
|
warning: _common_pb2.Warning
|
117
118
|
task: _common_pb2.Task
|
118
|
-
|
119
|
+
records: Records
|
120
|
+
def __init__(self, record: _Optional[_Union[Record, _Mapping]] = ..., schema_change: _Optional[_Union[SchemaChange, _Mapping]] = ..., checkpoint: _Optional[_Union[Checkpoint, _Mapping]] = ..., warning: _Optional[_Union[_common_pb2.Warning, _Mapping]] = ..., task: _Optional[_Union[_common_pb2.Task, _Mapping]] = ..., records: _Optional[_Union[Records, _Mapping]] = ...) -> None: ...
|
119
121
|
|
120
122
|
class SchemaChange(_message.Message):
|
121
123
|
__slots__ = ("with_schema", "without_schema")
|
@@ -125,6 +127,12 @@ class SchemaChange(_message.Message):
|
|
125
127
|
without_schema: _common_pb2.TableList
|
126
128
|
def __init__(self, with_schema: _Optional[_Union[_common_pb2.SchemaList, _Mapping]] = ..., without_schema: _Optional[_Union[_common_pb2.TableList, _Mapping]] = ...) -> None: ...
|
127
129
|
|
130
|
+
class Records(_message.Message):
|
131
|
+
__slots__ = ("records",)
|
132
|
+
RECORDS_FIELD_NUMBER: _ClassVar[int]
|
133
|
+
records: _containers.RepeatedCompositeFieldContainer[Record]
|
134
|
+
def __init__(self, records: _Optional[_Iterable[_Union[Record, _Mapping]]] = ...) -> None: ...
|
135
|
+
|
128
136
|
class Record(_message.Message):
|
129
137
|
__slots__ = ("schema_name", "table_name", "type", "data")
|
130
138
|
class DataEntry(_message.Message):
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: fivetran_connector_sdk
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.8.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
|
File without changes
|
File without changes
|
File without changes
|
{fivetran_connector_sdk-1.7.5 → fivetran_connector_sdk-1.8.0}/src/fivetran_connector_sdk/helpers.py
RENAMED
File without changes
|
{fivetran_connector_sdk-1.7.5 → fivetran_connector_sdk-1.8.0}/src/fivetran_connector_sdk/logger.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
|