airbyte-cdk 6.21.1.dev0__py3-none-any.whl → 6.26.0.dev4103__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.
- airbyte_cdk/cli/source_declarative_manifest/_run.py +6 -0
- airbyte_cdk/connector_builder/connector_builder_handler.py +1 -0
- airbyte_cdk/sources/declarative/auth/oauth.py +68 -11
- airbyte_cdk/sources/declarative/concurrent_declarative_source.py +81 -16
- airbyte_cdk/sources/declarative/declarative_component_schema.yaml +58 -2
- airbyte_cdk/sources/declarative/decoders/__init__.py +9 -1
- airbyte_cdk/sources/declarative/decoders/zipfile_decoder.py +59 -0
- airbyte_cdk/sources/declarative/extractors/record_filter.py +3 -5
- airbyte_cdk/sources/declarative/incremental/__init__.py +6 -0
- airbyte_cdk/sources/declarative/incremental/concurrent_partition_cursor.py +334 -0
- airbyte_cdk/sources/declarative/incremental/global_substream_cursor.py +3 -0
- airbyte_cdk/sources/declarative/incremental/per_partition_cursor.py +35 -3
- airbyte_cdk/sources/declarative/manifest_declarative_source.py +15 -4
- airbyte_cdk/sources/declarative/models/declarative_component_schema.py +50 -14
- airbyte_cdk/sources/declarative/parsers/custom_code_compiler.py +143 -0
- airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py +220 -22
- airbyte_cdk/sources/declarative/partition_routers/substream_partition_router.py +6 -2
- airbyte_cdk/sources/declarative/requesters/error_handlers/composite_error_handler.py +22 -0
- airbyte_cdk/sources/declarative/retrievers/simple_retriever.py +1 -1
- airbyte_cdk/sources/file_based/config/abstract_file_based_spec.py +15 -0
- airbyte_cdk/sources/file_based/config/identities_based_stream_config.py +8 -0
- airbyte_cdk/sources/file_based/config/permissions.py +34 -0
- airbyte_cdk/sources/file_based/file_based_source.py +65 -1
- airbyte_cdk/sources/file_based/file_based_stream_reader.py +33 -0
- airbyte_cdk/sources/file_based/schema_helpers.py +25 -0
- airbyte_cdk/sources/file_based/stream/__init__.py +2 -1
- airbyte_cdk/sources/file_based/stream/default_file_based_stream.py +29 -0
- airbyte_cdk/sources/file_based/stream/identities_stream.py +99 -0
- airbyte_cdk/sources/http_logger.py +1 -1
- airbyte_cdk/sources/streams/concurrent/clamping.py +99 -0
- airbyte_cdk/sources/streams/concurrent/cursor.py +51 -57
- airbyte_cdk/sources/streams/concurrent/cursor_types.py +32 -0
- airbyte_cdk/sources/streams/http/requests_native_auth/oauth.py +20 -20
- airbyte_cdk/test/utils/manifest_only_fixtures.py +1 -2
- {airbyte_cdk-6.21.1.dev0.dist-info → airbyte_cdk-6.26.0.dev4103.dist-info}/METADATA +3 -3
- {airbyte_cdk-6.21.1.dev0.dist-info → airbyte_cdk-6.26.0.dev4103.dist-info}/RECORD +39 -31
- {airbyte_cdk-6.21.1.dev0.dist-info → airbyte_cdk-6.26.0.dev4103.dist-info}/LICENSE.txt +0 -0
- {airbyte_cdk-6.21.1.dev0.dist-info → airbyte_cdk-6.26.0.dev4103.dist-info}/WHEEL +0 -0
- {airbyte_cdk-6.21.1.dev0.dist-info → airbyte_cdk-6.26.0.dev4103.dist-info}/entry_points.txt +0 -0
@@ -13,7 +13,6 @@ from typing import (
|
|
13
13
|
Mapping,
|
14
14
|
MutableMapping,
|
15
15
|
Optional,
|
16
|
-
Protocol,
|
17
16
|
Tuple,
|
18
17
|
Union,
|
19
18
|
)
|
@@ -21,6 +20,8 @@ from typing import (
|
|
21
20
|
from airbyte_cdk.sources.connector_state_manager import ConnectorStateManager
|
22
21
|
from airbyte_cdk.sources.message import MessageRepository
|
23
22
|
from airbyte_cdk.sources.streams import NO_CURSOR_STATE_KEY
|
23
|
+
from airbyte_cdk.sources.streams.concurrent.clamping import ClampingStrategy, NoClamping
|
24
|
+
from airbyte_cdk.sources.streams.concurrent.cursor_types import CursorValueType, GapType
|
24
25
|
from airbyte_cdk.sources.streams.concurrent.partitions.partition import Partition
|
25
26
|
from airbyte_cdk.sources.streams.concurrent.partitions.stream_slicer import StreamSlicer
|
26
27
|
from airbyte_cdk.sources.streams.concurrent.state_converters.abstract_stream_state_converter import (
|
@@ -35,36 +36,6 @@ def _extract_value(mapping: Mapping[str, Any], path: List[str]) -> Any:
|
|
35
36
|
return functools.reduce(lambda a, b: a[b], path, mapping)
|
36
37
|
|
37
38
|
|
38
|
-
class GapType(Protocol):
|
39
|
-
"""
|
40
|
-
This is the representation of gaps between two cursor values. Examples:
|
41
|
-
* if cursor values are datetimes, GapType is timedelta
|
42
|
-
* if cursor values are integer, GapType will also be integer
|
43
|
-
"""
|
44
|
-
|
45
|
-
pass
|
46
|
-
|
47
|
-
|
48
|
-
class CursorValueType(Protocol):
|
49
|
-
"""Protocol for annotating comparable types."""
|
50
|
-
|
51
|
-
@abstractmethod
|
52
|
-
def __lt__(self: "CursorValueType", other: "CursorValueType") -> bool:
|
53
|
-
pass
|
54
|
-
|
55
|
-
@abstractmethod
|
56
|
-
def __ge__(self: "CursorValueType", other: "CursorValueType") -> bool:
|
57
|
-
pass
|
58
|
-
|
59
|
-
@abstractmethod
|
60
|
-
def __add__(self: "CursorValueType", other: GapType) -> "CursorValueType":
|
61
|
-
pass
|
62
|
-
|
63
|
-
@abstractmethod
|
64
|
-
def __sub__(self: "CursorValueType", other: GapType) -> "CursorValueType":
|
65
|
-
pass
|
66
|
-
|
67
|
-
|
68
39
|
class CursorField:
|
69
40
|
def __init__(self, cursor_field_key: str) -> None:
|
70
41
|
self.cursor_field_key = cursor_field_key
|
@@ -172,6 +143,7 @@ class ConcurrentCursor(Cursor):
|
|
172
143
|
lookback_window: Optional[GapType] = None,
|
173
144
|
slice_range: Optional[GapType] = None,
|
174
145
|
cursor_granularity: Optional[GapType] = None,
|
146
|
+
clamping_strategy: ClampingStrategy = NoClamping(),
|
175
147
|
) -> None:
|
176
148
|
self._stream_name = stream_name
|
177
149
|
self._stream_namespace = stream_namespace
|
@@ -193,10 +165,13 @@ class ConcurrentCursor(Cursor):
|
|
193
165
|
self._cursor_granularity = cursor_granularity
|
194
166
|
# Flag to track if the logger has been triggered (per stream)
|
195
167
|
self._should_be_synced_logger_triggered = False
|
168
|
+
self._clamping_strategy = clamping_strategy
|
196
169
|
|
197
170
|
@property
|
198
171
|
def state(self) -> MutableMapping[str, Any]:
|
199
|
-
return self.
|
172
|
+
return self._connector_state_converter.convert_to_state_message(
|
173
|
+
self.cursor_field, self._concurrent_state
|
174
|
+
)
|
200
175
|
|
201
176
|
@property
|
202
177
|
def cursor_field(self) -> CursorField:
|
@@ -241,10 +216,10 @@ class ConcurrentCursor(Cursor):
|
|
241
216
|
return self._connector_state_converter.parse_value(self._cursor_field.extract_value(record))
|
242
217
|
|
243
218
|
def close_partition(self, partition: Partition) -> None:
|
244
|
-
slice_count_before = len(self.
|
219
|
+
slice_count_before = len(self._concurrent_state.get("slices", []))
|
245
220
|
self._add_slice_to_state(partition)
|
246
221
|
if slice_count_before < len(
|
247
|
-
self.
|
222
|
+
self._concurrent_state["slices"]
|
248
223
|
): # only emit if at least one slice has been processed
|
249
224
|
self._merge_partitions()
|
250
225
|
self._emit_state_message()
|
@@ -256,11 +231,11 @@ class ConcurrentCursor(Cursor):
|
|
256
231
|
)
|
257
232
|
|
258
233
|
if self._slice_boundary_fields:
|
259
|
-
if "slices" not in self.
|
234
|
+
if "slices" not in self._concurrent_state:
|
260
235
|
raise RuntimeError(
|
261
236
|
f"The state for stream {self._stream_name} should have at least one slice to delineate the sync start time, but no slices are present. This is unexpected. Please contact Support."
|
262
237
|
)
|
263
|
-
self.
|
238
|
+
self._concurrent_state["slices"].append(
|
264
239
|
{
|
265
240
|
self._connector_state_converter.START_KEY: self._extract_from_slice(
|
266
241
|
partition, self._slice_boundary_fields[self._START_BOUNDARY]
|
@@ -288,7 +263,7 @@ class ConcurrentCursor(Cursor):
|
|
288
263
|
"expected. Please contact the Airbyte team."
|
289
264
|
)
|
290
265
|
|
291
|
-
self.
|
266
|
+
self._concurrent_state["slices"].append(
|
292
267
|
{
|
293
268
|
self._connector_state_converter.START_KEY: self.start,
|
294
269
|
self._connector_state_converter.END_KEY: most_recent_cursor_value,
|
@@ -300,9 +275,7 @@ class ConcurrentCursor(Cursor):
|
|
300
275
|
self._connector_state_manager.update_state_for_stream(
|
301
276
|
self._stream_name,
|
302
277
|
self._stream_namespace,
|
303
|
-
self.
|
304
|
-
self._cursor_field, self.state
|
305
|
-
),
|
278
|
+
self.state,
|
306
279
|
)
|
307
280
|
state_message = self._connector_state_manager.create_state_message(
|
308
281
|
self._stream_name, self._stream_namespace
|
@@ -310,7 +283,9 @@ class ConcurrentCursor(Cursor):
|
|
310
283
|
self._message_repository.emit_message(state_message)
|
311
284
|
|
312
285
|
def _merge_partitions(self) -> None:
|
313
|
-
self.
|
286
|
+
self._concurrent_state["slices"] = self._connector_state_converter.merge_intervals(
|
287
|
+
self._concurrent_state["slices"]
|
288
|
+
)
|
314
289
|
|
315
290
|
def _extract_from_slice(self, partition: Partition, key: str) -> CursorValueType:
|
316
291
|
try:
|
@@ -347,36 +322,42 @@ class ConcurrentCursor(Cursor):
|
|
347
322
|
if self._start is not None and self._is_start_before_first_slice():
|
348
323
|
yield from self._split_per_slice_range(
|
349
324
|
self._start,
|
350
|
-
self.
|
325
|
+
self._concurrent_state["slices"][0][self._connector_state_converter.START_KEY],
|
351
326
|
False,
|
352
327
|
)
|
353
328
|
|
354
|
-
if len(self.
|
329
|
+
if len(self._concurrent_state["slices"]) == 1:
|
355
330
|
yield from self._split_per_slice_range(
|
356
331
|
self._calculate_lower_boundary_of_last_slice(
|
357
|
-
self.
|
332
|
+
self._concurrent_state["slices"][0][self._connector_state_converter.END_KEY]
|
358
333
|
),
|
359
334
|
self._end_provider(),
|
360
335
|
True,
|
361
336
|
)
|
362
|
-
elif len(self.
|
363
|
-
for i in range(len(self.
|
337
|
+
elif len(self._concurrent_state["slices"]) > 1:
|
338
|
+
for i in range(len(self._concurrent_state["slices"]) - 1):
|
364
339
|
if self._cursor_granularity:
|
365
340
|
yield from self._split_per_slice_range(
|
366
|
-
self.
|
341
|
+
self._concurrent_state["slices"][i][self._connector_state_converter.END_KEY]
|
367
342
|
+ self._cursor_granularity,
|
368
|
-
self.
|
343
|
+
self._concurrent_state["slices"][i + 1][
|
344
|
+
self._connector_state_converter.START_KEY
|
345
|
+
],
|
369
346
|
False,
|
370
347
|
)
|
371
348
|
else:
|
372
349
|
yield from self._split_per_slice_range(
|
373
|
-
self.
|
374
|
-
|
350
|
+
self._concurrent_state["slices"][i][
|
351
|
+
self._connector_state_converter.END_KEY
|
352
|
+
],
|
353
|
+
self._concurrent_state["slices"][i + 1][
|
354
|
+
self._connector_state_converter.START_KEY
|
355
|
+
],
|
375
356
|
False,
|
376
357
|
)
|
377
358
|
yield from self._split_per_slice_range(
|
378
359
|
self._calculate_lower_boundary_of_last_slice(
|
379
|
-
self.
|
360
|
+
self._concurrent_state["slices"][-1][self._connector_state_converter.END_KEY]
|
380
361
|
),
|
381
362
|
self._end_provider(),
|
382
363
|
True,
|
@@ -387,7 +368,8 @@ class ConcurrentCursor(Cursor):
|
|
387
368
|
def _is_start_before_first_slice(self) -> bool:
|
388
369
|
return (
|
389
370
|
self._start is not None
|
390
|
-
and self._start
|
371
|
+
and self._start
|
372
|
+
< self._concurrent_state["slices"][0][self._connector_state_converter.START_KEY]
|
391
373
|
)
|
392
374
|
|
393
375
|
def _calculate_lower_boundary_of_last_slice(
|
@@ -408,10 +390,12 @@ class ConcurrentCursor(Cursor):
|
|
408
390
|
|
409
391
|
lower = max(lower, self._start) if self._start else lower
|
410
392
|
if not self._slice_range or self._evaluate_upper_safely(lower, self._slice_range) >= upper:
|
393
|
+
clamped_lower = self._clamping_strategy.clamp(lower)
|
394
|
+
clamped_upper = self._clamping_strategy.clamp(upper)
|
411
395
|
start_value, end_value = (
|
412
|
-
(
|
396
|
+
(clamped_lower, clamped_upper - self._cursor_granularity)
|
413
397
|
if self._cursor_granularity and not upper_is_end
|
414
|
-
else (
|
398
|
+
else (clamped_lower, clamped_upper)
|
415
399
|
)
|
416
400
|
yield StreamSlice(
|
417
401
|
partition={},
|
@@ -433,11 +417,21 @@ class ConcurrentCursor(Cursor):
|
|
433
417
|
)
|
434
418
|
has_reached_upper_boundary = current_upper_boundary >= upper
|
435
419
|
|
420
|
+
clamped_upper = (
|
421
|
+
self._clamping_strategy.clamp(current_upper_boundary)
|
422
|
+
if current_upper_boundary != upper
|
423
|
+
else current_upper_boundary
|
424
|
+
)
|
425
|
+
clamped_lower = self._clamping_strategy.clamp(current_lower_boundary)
|
426
|
+
if clamped_lower >= clamped_upper:
|
427
|
+
# clamping collapsed both values which means that it is time to stop processing
|
428
|
+
# FIXME should this be replace by proper end_provider
|
429
|
+
break
|
436
430
|
start_value, end_value = (
|
437
|
-
(
|
431
|
+
(clamped_lower, clamped_upper - self._cursor_granularity)
|
438
432
|
if self._cursor_granularity
|
439
433
|
and (not upper_is_end or not has_reached_upper_boundary)
|
440
|
-
else (
|
434
|
+
else (clamped_lower, clamped_upper)
|
441
435
|
)
|
442
436
|
yield StreamSlice(
|
443
437
|
partition={},
|
@@ -450,7 +444,7 @@ class ConcurrentCursor(Cursor):
|
|
450
444
|
]: self._connector_state_converter.output_format(end_value),
|
451
445
|
},
|
452
446
|
)
|
453
|
-
current_lower_boundary =
|
447
|
+
current_lower_boundary = clamped_upper
|
454
448
|
if current_upper_boundary >= upper:
|
455
449
|
stop_processing = True
|
456
450
|
|
@@ -0,0 +1,32 @@
|
|
1
|
+
from abc import abstractmethod
|
2
|
+
from typing import Protocol
|
3
|
+
|
4
|
+
|
5
|
+
class GapType(Protocol):
|
6
|
+
"""
|
7
|
+
This is the representation of gaps between two cursor values. Examples:
|
8
|
+
* if cursor values are datetimes, GapType is timedelta
|
9
|
+
* if cursor values are integer, GapType will also be integer
|
10
|
+
"""
|
11
|
+
|
12
|
+
pass
|
13
|
+
|
14
|
+
|
15
|
+
class CursorValueType(Protocol):
|
16
|
+
"""Protocol for annotating comparable types."""
|
17
|
+
|
18
|
+
@abstractmethod
|
19
|
+
def __lt__(self: "CursorValueType", other: "CursorValueType") -> bool:
|
20
|
+
pass
|
21
|
+
|
22
|
+
@abstractmethod
|
23
|
+
def __ge__(self: "CursorValueType", other: "CursorValueType") -> bool:
|
24
|
+
pass
|
25
|
+
|
26
|
+
@abstractmethod
|
27
|
+
def __add__(self: "CursorValueType", other: GapType) -> "CursorValueType":
|
28
|
+
pass
|
29
|
+
|
30
|
+
@abstractmethod
|
31
|
+
def __sub__(self: "CursorValueType", other: GapType) -> "CursorValueType":
|
32
|
+
pass
|
@@ -95,16 +95,16 @@ class Oauth2Authenticator(AbstractOauth2Authenticator):
|
|
95
95
|
return self._access_token_name
|
96
96
|
|
97
97
|
def get_scopes(self) -> list[str]:
|
98
|
-
return self._scopes # type: ignore
|
98
|
+
return self._scopes # type: ignore[return-value]
|
99
99
|
|
100
100
|
def get_expires_in_name(self) -> str:
|
101
101
|
return self._expires_in_name
|
102
102
|
|
103
103
|
def get_refresh_request_body(self) -> Mapping[str, Any]:
|
104
|
-
return self._refresh_request_body # type: ignore
|
104
|
+
return self._refresh_request_body # type: ignore[return-value]
|
105
105
|
|
106
106
|
def get_refresh_request_headers(self) -> Mapping[str, Any]:
|
107
|
-
return self._refresh_request_headers # type: ignore
|
107
|
+
return self._refresh_request_headers # type: ignore[return-value]
|
108
108
|
|
109
109
|
def get_grant_type_name(self) -> str:
|
110
110
|
return self._grant_type_name
|
@@ -128,11 +128,11 @@ class Oauth2Authenticator(AbstractOauth2Authenticator):
|
|
128
128
|
|
129
129
|
@property
|
130
130
|
def access_token(self) -> str:
|
131
|
-
return self._access_token # type: ignore
|
131
|
+
return self._access_token # type: ignore[return-value]
|
132
132
|
|
133
133
|
@access_token.setter
|
134
134
|
def access_token(self, value: str) -> None:
|
135
|
-
self._access_token = value # type: ignore
|
135
|
+
self._access_token = value # type: ignore[assignment] # Incorrect type for assignment
|
136
136
|
|
137
137
|
|
138
138
|
class SingleUseRefreshTokenOauth2Authenticator(Oauth2Authenticator):
|
@@ -192,15 +192,15 @@ class SingleUseRefreshTokenOauth2Authenticator(Oauth2Authenticator):
|
|
192
192
|
message_repository (MessageRepository): the message repository used to emit logs on HTTP requests and control message on config update
|
193
193
|
"""
|
194
194
|
self._client_id = (
|
195
|
-
client_id # type: ignore
|
195
|
+
client_id # type: ignore[assignment] # Incorrect type for assignment
|
196
196
|
if client_id is not None
|
197
|
-
else dpath.get(connector_config, ("credentials", "client_id")) # type: ignore
|
197
|
+
else dpath.get(connector_config, ("credentials", "client_id")) # type: ignore[arg-type]
|
198
198
|
)
|
199
199
|
self._client_secret = (
|
200
|
-
client_secret # type: ignore
|
200
|
+
client_secret # type: ignore[assignment] # Incorrect type for assignment
|
201
201
|
if client_secret is not None
|
202
202
|
else dpath.get(
|
203
|
-
connector_config, # type: ignore
|
203
|
+
connector_config, # type: ignore[arg-type]
|
204
204
|
("credentials", "client_secret"),
|
205
205
|
)
|
206
206
|
)
|
@@ -248,8 +248,8 @@ class SingleUseRefreshTokenOauth2Authenticator(Oauth2Authenticator):
|
|
248
248
|
|
249
249
|
@property
|
250
250
|
def access_token(self) -> str:
|
251
|
-
return dpath.get( # type: ignore
|
252
|
-
self._connector_config, # type: ignore
|
251
|
+
return dpath.get( # type: ignore[return-value]
|
252
|
+
self._connector_config, # type: ignore[arg-type]
|
253
253
|
self._access_token_config_path,
|
254
254
|
default="",
|
255
255
|
)
|
@@ -257,39 +257,39 @@ class SingleUseRefreshTokenOauth2Authenticator(Oauth2Authenticator):
|
|
257
257
|
@access_token.setter
|
258
258
|
def access_token(self, new_access_token: str) -> None:
|
259
259
|
dpath.new(
|
260
|
-
self._connector_config, # type: ignore
|
260
|
+
self._connector_config, # type: ignore[arg-type]
|
261
261
|
self._access_token_config_path,
|
262
262
|
new_access_token,
|
263
263
|
)
|
264
264
|
|
265
265
|
def get_refresh_token(self) -> str:
|
266
|
-
return dpath.get( # type: ignore
|
267
|
-
self._connector_config, # type: ignore
|
266
|
+
return dpath.get( # type: ignore[return-value]
|
267
|
+
self._connector_config, # type: ignore[arg-type]
|
268
268
|
self._refresh_token_config_path,
|
269
269
|
default="",
|
270
270
|
)
|
271
271
|
|
272
272
|
def set_refresh_token(self, new_refresh_token: str) -> None:
|
273
273
|
dpath.new(
|
274
|
-
self._connector_config, # type: ignore
|
274
|
+
self._connector_config, # type: ignore[arg-type]
|
275
275
|
self._refresh_token_config_path,
|
276
276
|
new_refresh_token,
|
277
277
|
)
|
278
278
|
|
279
279
|
def get_token_expiry_date(self) -> pendulum.DateTime:
|
280
280
|
expiry_date = dpath.get(
|
281
|
-
self._connector_config, # type: ignore
|
281
|
+
self._connector_config, # type: ignore[arg-type]
|
282
282
|
self._token_expiry_date_config_path,
|
283
283
|
default="",
|
284
284
|
)
|
285
|
-
return pendulum.now().subtract(days=1) if expiry_date == "" else pendulum.parse(expiry_date) # type: ignore
|
285
|
+
return pendulum.now().subtract(days=1) if expiry_date == "" else pendulum.parse(expiry_date) # type: ignore[arg-type, return-value, no-untyped-call]
|
286
286
|
|
287
287
|
def set_token_expiry_date( # type: ignore[override]
|
288
288
|
self,
|
289
289
|
new_token_expiry_date: pendulum.DateTime,
|
290
290
|
) -> None:
|
291
291
|
dpath.new(
|
292
|
-
self._connector_config, # type: ignore
|
292
|
+
self._connector_config, # type: ignore[arg-type]
|
293
293
|
self._token_expiry_date_config_path,
|
294
294
|
str(new_token_expiry_date),
|
295
295
|
)
|
@@ -329,10 +329,10 @@ class SingleUseRefreshTokenOauth2Authenticator(Oauth2Authenticator):
|
|
329
329
|
# message directly in the console, this is needed
|
330
330
|
if not isinstance(self._message_repository, NoopMessageRepository):
|
331
331
|
self._message_repository.emit_message(
|
332
|
-
create_connector_config_control_message(self._connector_config) # type: ignore
|
332
|
+
create_connector_config_control_message(self._connector_config) # type: ignore[arg-type]
|
333
333
|
)
|
334
334
|
else:
|
335
|
-
emit_configuration_as_airbyte_control_message(self._connector_config) # type: ignore
|
335
|
+
emit_configuration_as_airbyte_control_message(self._connector_config) # type: ignore[arg-type]
|
336
336
|
return self.access_token
|
337
337
|
|
338
338
|
def refresh_access_token( # type: ignore[override] # Signature doesn't match base class
|
@@ -4,7 +4,6 @@
|
|
4
4
|
import importlib.util
|
5
5
|
from pathlib import Path
|
6
6
|
from types import ModuleType
|
7
|
-
from typing import Optional
|
8
7
|
|
9
8
|
import pytest
|
10
9
|
|
@@ -30,7 +29,7 @@ def connector_dir(request: pytest.FixtureRequest) -> Path:
|
|
30
29
|
|
31
30
|
|
32
31
|
@pytest.fixture(scope="session")
|
33
|
-
def components_module(connector_dir: Path) ->
|
32
|
+
def components_module(connector_dir: Path) -> ModuleType | None:
|
34
33
|
"""Load and return the components module from the connector directory.
|
35
34
|
|
36
35
|
This assumes the components module is located at <connector_dir>/components.py.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: airbyte-cdk
|
3
|
-
Version: 6.
|
3
|
+
Version: 6.26.0.dev4103
|
4
4
|
Summary: A framework for writing Airbyte Connectors.
|
5
5
|
License: MIT
|
6
6
|
Keywords: airbyte,connector-development-kit,cdk
|
@@ -23,7 +23,7 @@ Requires-Dist: Jinja2 (>=3.1.2,<3.2.0)
|
|
23
23
|
Requires-Dist: PyYAML (>=6.0.1,<7.0.0)
|
24
24
|
Requires-Dist: Unidecode (>=1.3,<2.0)
|
25
25
|
Requires-Dist: airbyte-protocol-models-dataclasses (>=0.14,<0.15)
|
26
|
-
Requires-Dist: avro (>=1.11.2,<1.
|
26
|
+
Requires-Dist: avro (>=1.11.2,<1.13.0) ; extra == "file-based"
|
27
27
|
Requires-Dist: backoff
|
28
28
|
Requires-Dist: cachetools
|
29
29
|
Requires-Dist: cohere (==4.21) ; extra == "vector-db-based"
|
@@ -66,7 +66,7 @@ Requires-Dist: tiktoken (==0.8.0) ; extra == "vector-db-based"
|
|
66
66
|
Requires-Dist: unstructured.pytesseract (>=0.3.12) ; extra == "file-based"
|
67
67
|
Requires-Dist: unstructured[docx,pptx] (==0.10.27) ; extra == "file-based"
|
68
68
|
Requires-Dist: wcmatch (==10.0)
|
69
|
-
Requires-Dist: xmltodict (>=0.13
|
69
|
+
Requires-Dist: xmltodict (>=0.13,<0.15)
|
70
70
|
Project-URL: Documentation, https://docs.airbyte.io/
|
71
71
|
Project-URL: Homepage, https://airbyte.com
|
72
72
|
Project-URL: Repository, https://github.com/airbytehq/airbyte-python-cdk
|