airbyte-cdk 6.11.2.dev1__py3-none-any.whl → 6.12.0__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/sources/declarative/declarative_component_schema.yaml +43 -1
- airbyte_cdk/sources/declarative/models/declarative_component_schema.py +36 -1
- airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py +38 -15
- airbyte_cdk/sources/declarative/partition_routers/__init__.py +1 -9
- airbyte_cdk/sources/declarative/retrievers/async_retriever.py +31 -8
- airbyte_cdk/sources/declarative/schema/dynamic_schema_loader.py +20 -3
- airbyte_cdk/sources/declarative/transformations/flatten_fields.py +50 -0
- airbyte_cdk/sources/declarative/transformations/keys_to_snake_transformation.py +68 -0
- airbyte_cdk/sources/streams/http/http_client.py +4 -2
- {airbyte_cdk-6.11.2.dev1.dist-info → airbyte_cdk-6.12.0.dist-info}/METADATA +2 -1
- {airbyte_cdk-6.11.2.dev1.dist-info → airbyte_cdk-6.12.0.dist-info}/RECORD +14 -13
- airbyte_cdk/sources/declarative/partition_routers/async_job_partition_router.py +0 -65
- {airbyte_cdk-6.11.2.dev1.dist-info → airbyte_cdk-6.12.0.dist-info}/LICENSE.txt +0 -0
- {airbyte_cdk-6.11.2.dev1.dist-info → airbyte_cdk-6.12.0.dist-info}/WHEEL +0 -0
- {airbyte_cdk-6.11.2.dev1.dist-info → airbyte_cdk-6.12.0.dist-info}/entry_points.txt +0 -0
@@ -1234,6 +1234,8 @@ definitions:
|
|
1234
1234
|
- "$ref": "#/definitions/CustomTransformation"
|
1235
1235
|
- "$ref": "#/definitions/RemoveFields"
|
1236
1236
|
- "$ref": "#/definitions/KeysToLower"
|
1237
|
+
- "$ref": "#/definitions/KeysToSnakeCase"
|
1238
|
+
- "$ref": "#/definitions/FlattenFields"
|
1237
1239
|
state_migrations:
|
1238
1240
|
title: State Migrations
|
1239
1241
|
description: Array of state migrations to be applied on the input state
|
@@ -1766,6 +1768,18 @@ definitions:
|
|
1766
1768
|
- "$ref": "#/definitions/AsyncRetriever"
|
1767
1769
|
- "$ref": "#/definitions/CustomRetriever"
|
1768
1770
|
- "$ref": "#/definitions/SimpleRetriever"
|
1771
|
+
schema_transformations:
|
1772
|
+
title: Schema Transformations
|
1773
|
+
description: A list of transformations to be applied to the schema.
|
1774
|
+
type: array
|
1775
|
+
items:
|
1776
|
+
anyOf:
|
1777
|
+
- "$ref": "#/definitions/AddFields"
|
1778
|
+
- "$ref": "#/definitions/CustomTransformation"
|
1779
|
+
- "$ref": "#/definitions/RemoveFields"
|
1780
|
+
- "$ref": "#/definitions/KeysToLower"
|
1781
|
+
- "$ref": "#/definitions/KeysToSnakeCase"
|
1782
|
+
- "$ref": "#/definitions/FlattenFields"
|
1769
1783
|
schema_type_identifier:
|
1770
1784
|
"$ref": "#/definitions/SchemaTypeIdentifier"
|
1771
1785
|
$parameters:
|
@@ -1838,6 +1852,32 @@ definitions:
|
|
1838
1852
|
$parameters:
|
1839
1853
|
type: object
|
1840
1854
|
additionalProperties: true
|
1855
|
+
KeysToSnakeCase:
|
1856
|
+
title: Key to Snake Case
|
1857
|
+
description: A transformation that renames all keys to snake case.
|
1858
|
+
type: object
|
1859
|
+
required:
|
1860
|
+
- type
|
1861
|
+
properties:
|
1862
|
+
type:
|
1863
|
+
type: string
|
1864
|
+
enum: [KeysToSnakeCase]
|
1865
|
+
$parameters:
|
1866
|
+
type: object
|
1867
|
+
additionalProperties: true
|
1868
|
+
FlattenFields:
|
1869
|
+
title: Flatten Fields
|
1870
|
+
description: A transformation that flatten record to single level format.
|
1871
|
+
type: object
|
1872
|
+
required:
|
1873
|
+
- type
|
1874
|
+
properties:
|
1875
|
+
type:
|
1876
|
+
type: string
|
1877
|
+
enum: [FlattenFields]
|
1878
|
+
$parameters:
|
1879
|
+
type: object
|
1880
|
+
additionalProperties: true
|
1841
1881
|
IterableDecoder:
|
1842
1882
|
title: Iterable Decoder
|
1843
1883
|
description: Use this if the response consists of strings separated by new lines (`\n`). The Decoder will wrap each row into a JSON object with the `record` key.
|
@@ -2160,7 +2200,9 @@ definitions:
|
|
2160
2200
|
description: |-
|
2161
2201
|
The DeclarativeOAuth Specific optional headers to inject while exchanging the `auth_code` to `access_token` during `completeOAuthFlow` step.
|
2162
2202
|
examples:
|
2163
|
-
- {
|
2203
|
+
- {
|
2204
|
+
"Authorization": "Basic {base64Encoder:{client_id}:{client_secret}}",
|
2205
|
+
}
|
2164
2206
|
access_token_params:
|
2165
2207
|
title: Access Token Query Params (Json Encoded)
|
2166
2208
|
type: object
|
@@ -710,6 +710,16 @@ class KeysToLower(BaseModel):
|
|
710
710
|
parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
|
711
711
|
|
712
712
|
|
713
|
+
class KeysToSnakeCase(BaseModel):
|
714
|
+
type: Literal["KeysToSnakeCase"]
|
715
|
+
parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
|
716
|
+
|
717
|
+
|
718
|
+
class FlattenFields(BaseModel):
|
719
|
+
type: Literal["FlattenFields"]
|
720
|
+
parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
|
721
|
+
|
722
|
+
|
713
723
|
class IterableDecoder(BaseModel):
|
714
724
|
type: Literal["IterableDecoder"]
|
715
725
|
|
@@ -1654,7 +1664,16 @@ class DeclarativeStream(BaseModel):
|
|
1654
1664
|
title="Schema Loader",
|
1655
1665
|
)
|
1656
1666
|
transformations: Optional[
|
1657
|
-
List[
|
1667
|
+
List[
|
1668
|
+
Union[
|
1669
|
+
AddFields,
|
1670
|
+
CustomTransformation,
|
1671
|
+
RemoveFields,
|
1672
|
+
KeysToLower,
|
1673
|
+
KeysToSnakeCase,
|
1674
|
+
FlattenFields,
|
1675
|
+
]
|
1676
|
+
]
|
1658
1677
|
] = Field(
|
1659
1678
|
None,
|
1660
1679
|
description="A list of transformations to be applied to each output record.",
|
@@ -1818,6 +1837,22 @@ class DynamicSchemaLoader(BaseModel):
|
|
1818
1837
|
description="Component used to coordinate how records are extracted across stream slices and request pages.",
|
1819
1838
|
title="Retriever",
|
1820
1839
|
)
|
1840
|
+
schema_transformations: Optional[
|
1841
|
+
List[
|
1842
|
+
Union[
|
1843
|
+
AddFields,
|
1844
|
+
CustomTransformation,
|
1845
|
+
RemoveFields,
|
1846
|
+
KeysToLower,
|
1847
|
+
KeysToSnakeCase,
|
1848
|
+
FlattenFields,
|
1849
|
+
]
|
1850
|
+
]
|
1851
|
+
] = Field(
|
1852
|
+
None,
|
1853
|
+
description="A list of transformations to be applied to the schema.",
|
1854
|
+
title="Schema Transformations",
|
1855
|
+
)
|
1821
1856
|
schema_type_identifier: SchemaTypeIdentifier
|
1822
1857
|
parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
|
1823
1858
|
|
@@ -197,6 +197,9 @@ from airbyte_cdk.sources.declarative.models.declarative_component_schema import
|
|
197
197
|
from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
|
198
198
|
ExponentialBackoffStrategy as ExponentialBackoffStrategyModel,
|
199
199
|
)
|
200
|
+
from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
|
201
|
+
FlattenFields as FlattenFieldsModel,
|
202
|
+
)
|
200
203
|
from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
|
201
204
|
GzipJsonDecoder as GzipJsonDecoderModel,
|
202
205
|
)
|
@@ -236,6 +239,9 @@ from airbyte_cdk.sources.declarative.models.declarative_component_schema import
|
|
236
239
|
from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
|
237
240
|
KeysToLower as KeysToLowerModel,
|
238
241
|
)
|
242
|
+
from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
|
243
|
+
KeysToSnakeCase as KeysToSnakeCaseModel,
|
244
|
+
)
|
239
245
|
from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
|
240
246
|
LegacySessionTokenAuthenticator as LegacySessionTokenAuthenticatorModel,
|
241
247
|
)
|
@@ -323,9 +329,6 @@ from airbyte_cdk.sources.declarative.partition_routers import (
|
|
323
329
|
SinglePartitionRouter,
|
324
330
|
SubstreamPartitionRouter,
|
325
331
|
)
|
326
|
-
from airbyte_cdk.sources.declarative.partition_routers.async_job_partition_router import (
|
327
|
-
AsyncJobPartitionRouter,
|
328
|
-
)
|
329
332
|
from airbyte_cdk.sources.declarative.partition_routers.substream_partition_router import (
|
330
333
|
ParentStreamConfig,
|
331
334
|
)
|
@@ -390,9 +393,15 @@ from airbyte_cdk.sources.declarative.transformations import (
|
|
390
393
|
RemoveFields,
|
391
394
|
)
|
392
395
|
from airbyte_cdk.sources.declarative.transformations.add_fields import AddedFieldDefinition
|
396
|
+
from airbyte_cdk.sources.declarative.transformations.flatten_fields import (
|
397
|
+
FlattenFields,
|
398
|
+
)
|
393
399
|
from airbyte_cdk.sources.declarative.transformations.keys_to_lower_transformation import (
|
394
400
|
KeysToLowerTransformation,
|
395
401
|
)
|
402
|
+
from airbyte_cdk.sources.declarative.transformations.keys_to_snake_transformation import (
|
403
|
+
KeysToSnakeCaseTransformation,
|
404
|
+
)
|
396
405
|
from airbyte_cdk.sources.message import (
|
397
406
|
InMemoryMessageRepository,
|
398
407
|
LogAppenderMessageRepositoryDecorator,
|
@@ -475,6 +484,8 @@ class ModelToComponentFactory:
|
|
475
484
|
JsonlDecoderModel: self.create_jsonl_decoder,
|
476
485
|
GzipJsonDecoderModel: self.create_gzipjson_decoder,
|
477
486
|
KeysToLowerModel: self.create_keys_to_lower_transformation,
|
487
|
+
KeysToSnakeCaseModel: self.create_keys_to_snake_transformation,
|
488
|
+
FlattenFieldsModel: self.create_flatten_fields,
|
478
489
|
IterableDecoderModel: self.create_iterable_decoder,
|
479
490
|
XmlDecoderModel: self.create_xml_decoder,
|
480
491
|
JsonFileSchemaLoaderModel: self.create_json_file_schema_loader,
|
@@ -590,6 +601,16 @@ class ModelToComponentFactory:
|
|
590
601
|
) -> KeysToLowerTransformation:
|
591
602
|
return KeysToLowerTransformation()
|
592
603
|
|
604
|
+
def create_keys_to_snake_transformation(
|
605
|
+
self, model: KeysToSnakeCaseModel, config: Config, **kwargs: Any
|
606
|
+
) -> KeysToSnakeCaseTransformation:
|
607
|
+
return KeysToSnakeCaseTransformation()
|
608
|
+
|
609
|
+
def create_flatten_fields(
|
610
|
+
self, model: FlattenFieldsModel, config: Config, **kwargs: Any
|
611
|
+
) -> FlattenFields:
|
612
|
+
return FlattenFields()
|
613
|
+
|
593
614
|
@staticmethod
|
594
615
|
def _json_schema_type_name_to_type(value_type: Optional[ValueType]) -> Optional[Type[Any]]:
|
595
616
|
if not value_type:
|
@@ -1641,6 +1662,13 @@ class ModelToComponentFactory:
|
|
1641
1662
|
model.retriever, stream_slicer
|
1642
1663
|
)
|
1643
1664
|
|
1665
|
+
schema_transformations = []
|
1666
|
+
if model.schema_transformations:
|
1667
|
+
for transformation_model in model.schema_transformations:
|
1668
|
+
schema_transformations.append(
|
1669
|
+
self._create_component_from_model(model=transformation_model, config=config)
|
1670
|
+
)
|
1671
|
+
|
1644
1672
|
retriever = self._create_component_from_model(
|
1645
1673
|
model=model.retriever,
|
1646
1674
|
config=config,
|
@@ -1655,6 +1683,7 @@ class ModelToComponentFactory:
|
|
1655
1683
|
return DynamicSchemaLoader(
|
1656
1684
|
retriever=retriever,
|
1657
1685
|
config=config,
|
1686
|
+
schema_transformations=schema_transformations,
|
1658
1687
|
schema_type_identifier=schema_type_identifier,
|
1659
1688
|
parameters=model.parameters or {},
|
1660
1689
|
)
|
@@ -2231,24 +2260,18 @@ class ModelToComponentFactory:
|
|
2231
2260
|
urls_extractor=urls_extractor,
|
2232
2261
|
)
|
2233
2262
|
|
2234
|
-
|
2263
|
+
return AsyncRetriever(
|
2235
2264
|
job_orchestrator_factory=lambda stream_slices: AsyncJobOrchestrator(
|
2236
2265
|
job_repository,
|
2237
2266
|
stream_slices,
|
2238
|
-
JobTracker(
|
2239
|
-
|
2267
|
+
JobTracker(
|
2268
|
+
1
|
2269
|
+
), # FIXME eventually make the number of concurrent jobs in the API configurable. Until then, we limit to 1
|
2240
2270
|
self._message_repository,
|
2241
|
-
has_bulk_parent=False,
|
2242
|
-
# FIXME work would need to be done here in order to detect if a stream as a parent stream that is bulk
|
2271
|
+
has_bulk_parent=False, # FIXME work would need to be done here in order to detect if a stream as a parent stream that is bulk
|
2243
2272
|
),
|
2244
|
-
stream_slicer=stream_slicer,
|
2245
|
-
config=config,
|
2246
|
-
parameters=model.parameters or {},
|
2247
|
-
)
|
2248
|
-
|
2249
|
-
return AsyncRetriever(
|
2250
2273
|
record_selector=record_selector,
|
2251
|
-
stream_slicer=
|
2274
|
+
stream_slicer=stream_slicer,
|
2252
2275
|
config=config,
|
2253
2276
|
parameters=model.parameters or {},
|
2254
2277
|
)
|
@@ -2,18 +2,10 @@
|
|
2
2
|
# Copyright (c) 2022 Airbyte, Inc., all rights reserved.
|
3
3
|
#
|
4
4
|
|
5
|
-
from airbyte_cdk.sources.declarative.partition_routers.async_job_partition_router import AsyncJobPartitionRouter
|
6
5
|
from airbyte_cdk.sources.declarative.partition_routers.cartesian_product_stream_slicer import CartesianProductStreamSlicer
|
7
6
|
from airbyte_cdk.sources.declarative.partition_routers.list_partition_router import ListPartitionRouter
|
8
7
|
from airbyte_cdk.sources.declarative.partition_routers.single_partition_router import SinglePartitionRouter
|
9
8
|
from airbyte_cdk.sources.declarative.partition_routers.substream_partition_router import SubstreamPartitionRouter
|
10
9
|
from airbyte_cdk.sources.declarative.partition_routers.partition_router import PartitionRouter
|
11
10
|
|
12
|
-
__all__ = [
|
13
|
-
"AsyncJobPartitionRouter",
|
14
|
-
"CartesianProductStreamSlicer",
|
15
|
-
"ListPartitionRouter",
|
16
|
-
"SinglePartitionRouter",
|
17
|
-
"SubstreamPartitionRouter",
|
18
|
-
"PartitionRouter"
|
19
|
-
]
|
11
|
+
__all__ = ["CartesianProductStreamSlicer", "ListPartitionRouter", "SinglePartitionRouter", "SubstreamPartitionRouter", "PartitionRouter"]
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# Copyright (c) 2024 Airbyte, Inc., all rights reserved.
|
2
2
|
|
3
3
|
|
4
|
-
from dataclasses import InitVar, dataclass
|
5
|
-
from typing import Any, Iterable, Mapping, Optional
|
4
|
+
from dataclasses import InitVar, dataclass, field
|
5
|
+
from typing import Any, Callable, Iterable, Mapping, Optional
|
6
6
|
|
7
7
|
from typing_extensions import deprecated
|
8
8
|
|
@@ -12,10 +12,9 @@ from airbyte_cdk.sources.declarative.async_job.job_orchestrator import (
|
|
12
12
|
AsyncPartition,
|
13
13
|
)
|
14
14
|
from airbyte_cdk.sources.declarative.extractors.record_selector import RecordSelector
|
15
|
-
from airbyte_cdk.sources.declarative.partition_routers
|
16
|
-
AsyncJobPartitionRouter,
|
17
|
-
)
|
15
|
+
from airbyte_cdk.sources.declarative.partition_routers import SinglePartitionRouter
|
18
16
|
from airbyte_cdk.sources.declarative.retrievers import Retriever
|
17
|
+
from airbyte_cdk.sources.declarative.stream_slicers import StreamSlicer
|
19
18
|
from airbyte_cdk.sources.source import ExperimentalClassWarning
|
20
19
|
from airbyte_cdk.sources.streams.core import StreamData
|
21
20
|
from airbyte_cdk.sources.types import Config, StreamSlice, StreamState
|
@@ -30,10 +29,15 @@ from airbyte_cdk.utils.traced_exception import AirbyteTracedException
|
|
30
29
|
class AsyncRetriever(Retriever):
|
31
30
|
config: Config
|
32
31
|
parameters: InitVar[Mapping[str, Any]]
|
32
|
+
job_orchestrator_factory: Callable[[Iterable[StreamSlice]], AsyncJobOrchestrator]
|
33
33
|
record_selector: RecordSelector
|
34
|
-
stream_slicer:
|
34
|
+
stream_slicer: StreamSlicer = field(
|
35
|
+
default_factory=lambda: SinglePartitionRouter(parameters={})
|
36
|
+
)
|
35
37
|
|
36
38
|
def __post_init__(self, parameters: Mapping[str, Any]) -> None:
|
39
|
+
self._job_orchestrator_factory = self.job_orchestrator_factory
|
40
|
+
self.__job_orchestrator: Optional[AsyncJobOrchestrator] = None
|
37
41
|
self._parameters = parameters
|
38
42
|
|
39
43
|
@property
|
@@ -50,6 +54,17 @@ class AsyncRetriever(Retriever):
|
|
50
54
|
"""
|
51
55
|
pass
|
52
56
|
|
57
|
+
@property
|
58
|
+
def _job_orchestrator(self) -> AsyncJobOrchestrator:
|
59
|
+
if not self.__job_orchestrator:
|
60
|
+
raise AirbyteTracedException(
|
61
|
+
message="Invalid state within AsyncJobRetriever. Please contact Airbyte Support",
|
62
|
+
internal_message="AsyncPartitionRepository is expected to be accessed only after `stream_slices`",
|
63
|
+
failure_type=FailureType.system_error,
|
64
|
+
)
|
65
|
+
|
66
|
+
return self.__job_orchestrator
|
67
|
+
|
53
68
|
def _get_stream_state(self) -> StreamState:
|
54
69
|
"""
|
55
70
|
Gets the current state of the stream.
|
@@ -84,7 +99,15 @@ class AsyncRetriever(Retriever):
|
|
84
99
|
return stream_slice["partition"] # type: ignore # stream_slice["partition"] has been added as an AsyncPartition as part of stream_slices
|
85
100
|
|
86
101
|
def stream_slices(self) -> Iterable[Optional[StreamSlice]]:
|
87
|
-
|
102
|
+
slices = self.stream_slicer.stream_slices()
|
103
|
+
self.__job_orchestrator = self._job_orchestrator_factory(slices)
|
104
|
+
|
105
|
+
for completed_partition in self._job_orchestrator.create_and_get_completed_partitions():
|
106
|
+
yield StreamSlice(
|
107
|
+
partition=dict(completed_partition.stream_slice.partition)
|
108
|
+
| {"partition": completed_partition},
|
109
|
+
cursor_slice=completed_partition.stream_slice.cursor_slice,
|
110
|
+
)
|
88
111
|
|
89
112
|
def read_records(
|
90
113
|
self,
|
@@ -93,7 +116,7 @@ class AsyncRetriever(Retriever):
|
|
93
116
|
) -> Iterable[StreamData]:
|
94
117
|
stream_state: StreamState = self._get_stream_state()
|
95
118
|
partition: AsyncPartition = self._validate_and_get_stream_slice_partition(stream_slice)
|
96
|
-
records: Iterable[Mapping[str, Any]] = self.
|
119
|
+
records: Iterable[Mapping[str, Any]] = self._job_orchestrator.fetch_records(partition)
|
97
120
|
|
98
121
|
yield from self.record_selector.filter_and_transform(
|
99
122
|
all_data=records,
|
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
|
6
6
|
from copy import deepcopy
|
7
|
-
from dataclasses import InitVar, dataclass
|
7
|
+
from dataclasses import InitVar, dataclass, field
|
8
8
|
from typing import Any, List, Mapping, MutableMapping, Optional, Union
|
9
9
|
|
10
10
|
import dpath
|
@@ -13,8 +13,9 @@ from typing_extensions import deprecated
|
|
13
13
|
from airbyte_cdk.sources.declarative.interpolation.interpolated_string import InterpolatedString
|
14
14
|
from airbyte_cdk.sources.declarative.retrievers.retriever import Retriever
|
15
15
|
from airbyte_cdk.sources.declarative.schema.schema_loader import SchemaLoader
|
16
|
+
from airbyte_cdk.sources.declarative.transformations import RecordTransformation
|
16
17
|
from airbyte_cdk.sources.source import ExperimentalClassWarning
|
17
|
-
from airbyte_cdk.sources.types import Config
|
18
|
+
from airbyte_cdk.sources.types import Config, StreamSlice, StreamState
|
18
19
|
|
19
20
|
AIRBYTE_DATA_TYPES: Mapping[str, Mapping[str, Any]] = {
|
20
21
|
"string": {"type": ["null", "string"]},
|
@@ -103,6 +104,7 @@ class DynamicSchemaLoader(SchemaLoader):
|
|
103
104
|
config: Config
|
104
105
|
parameters: InitVar[Mapping[str, Any]]
|
105
106
|
schema_type_identifier: SchemaTypeIdentifier
|
107
|
+
schema_transformations: List[RecordTransformation] = field(default_factory=lambda: [])
|
106
108
|
|
107
109
|
def get_json_schema(self) -> Mapping[str, Any]:
|
108
110
|
"""
|
@@ -128,12 +130,27 @@ class DynamicSchemaLoader(SchemaLoader):
|
|
128
130
|
)
|
129
131
|
properties[key] = value
|
130
132
|
|
133
|
+
transformed_properties = self._transform(properties, {})
|
134
|
+
|
131
135
|
return {
|
132
136
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
133
137
|
"type": "object",
|
134
|
-
"properties":
|
138
|
+
"properties": transformed_properties,
|
135
139
|
}
|
136
140
|
|
141
|
+
def _transform(
|
142
|
+
self,
|
143
|
+
properties: Mapping[str, Any],
|
144
|
+
stream_state: StreamState,
|
145
|
+
stream_slice: Optional[StreamSlice] = None,
|
146
|
+
) -> Mapping[str, Any]:
|
147
|
+
for transformation in self.schema_transformations:
|
148
|
+
transformation.transform(
|
149
|
+
properties, # type: ignore # properties has type Mapping[str, Any], but Dict[str, Any] expected
|
150
|
+
config=self.config,
|
151
|
+
)
|
152
|
+
return properties
|
153
|
+
|
137
154
|
def _get_key(
|
138
155
|
self,
|
139
156
|
raw_schema: MutableMapping[str, Any],
|
@@ -0,0 +1,50 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2024 Airbyte, Inc., all rights reserved.
|
3
|
+
#
|
4
|
+
|
5
|
+
from dataclasses import dataclass
|
6
|
+
from typing import Any, Dict, Optional
|
7
|
+
|
8
|
+
from airbyte_cdk.sources.declarative.transformations import RecordTransformation
|
9
|
+
from airbyte_cdk.sources.types import Config, StreamSlice, StreamState
|
10
|
+
|
11
|
+
|
12
|
+
@dataclass
|
13
|
+
class FlattenFields(RecordTransformation):
|
14
|
+
def transform(
|
15
|
+
self,
|
16
|
+
record: Dict[str, Any],
|
17
|
+
config: Optional[Config] = None,
|
18
|
+
stream_state: Optional[StreamState] = None,
|
19
|
+
stream_slice: Optional[StreamSlice] = None,
|
20
|
+
) -> None:
|
21
|
+
transformed_record = self.flatten_record(record)
|
22
|
+
record.clear()
|
23
|
+
record.update(transformed_record)
|
24
|
+
|
25
|
+
def flatten_record(self, record: Dict[str, Any]) -> Dict[str, Any]:
|
26
|
+
stack = [(record, "_")]
|
27
|
+
transformed_record: Dict[str, Any] = {}
|
28
|
+
force_with_parent_name = False
|
29
|
+
|
30
|
+
while stack:
|
31
|
+
current_record, parent_key = stack.pop()
|
32
|
+
|
33
|
+
if isinstance(current_record, dict):
|
34
|
+
for current_key, value in current_record.items():
|
35
|
+
new_key = (
|
36
|
+
f"{parent_key}.{current_key}"
|
37
|
+
if (current_key in transformed_record or force_with_parent_name)
|
38
|
+
else current_key
|
39
|
+
)
|
40
|
+
stack.append((value, new_key))
|
41
|
+
|
42
|
+
elif isinstance(current_record, list):
|
43
|
+
for i, item in enumerate(current_record):
|
44
|
+
force_with_parent_name = True
|
45
|
+
stack.append((item, f"{parent_key}.{i}"))
|
46
|
+
|
47
|
+
else:
|
48
|
+
transformed_record[parent_key] = current_record
|
49
|
+
|
50
|
+
return transformed_record
|
@@ -0,0 +1,68 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2024 Airbyte, Inc., all rights reserved.
|
3
|
+
#
|
4
|
+
|
5
|
+
import re
|
6
|
+
from dataclasses import dataclass
|
7
|
+
from typing import Any, Dict, List, Optional
|
8
|
+
|
9
|
+
import unidecode
|
10
|
+
|
11
|
+
from airbyte_cdk.sources.declarative.transformations import RecordTransformation
|
12
|
+
from airbyte_cdk.sources.types import Config, StreamSlice, StreamState
|
13
|
+
|
14
|
+
|
15
|
+
@dataclass
|
16
|
+
class KeysToSnakeCaseTransformation(RecordTransformation):
|
17
|
+
token_pattern: re.Pattern[str] = re.compile(
|
18
|
+
r"[A-Z]+[a-z]*|[a-z]+|\d+|(?P<NoToken>[^a-zA-Z\d]+)"
|
19
|
+
)
|
20
|
+
|
21
|
+
def transform(
|
22
|
+
self,
|
23
|
+
record: Dict[str, Any],
|
24
|
+
config: Optional[Config] = None,
|
25
|
+
stream_state: Optional[StreamState] = None,
|
26
|
+
stream_slice: Optional[StreamSlice] = None,
|
27
|
+
) -> None:
|
28
|
+
transformed_record = self._transform_record(record)
|
29
|
+
record.clear()
|
30
|
+
record.update(transformed_record)
|
31
|
+
|
32
|
+
def _transform_record(self, record: Dict[str, Any]) -> Dict[str, Any]:
|
33
|
+
transformed_record = {}
|
34
|
+
for key, value in record.items():
|
35
|
+
transformed_key = self.process_key(key)
|
36
|
+
transformed_value = value
|
37
|
+
|
38
|
+
if isinstance(value, dict):
|
39
|
+
transformed_value = self._transform_record(value)
|
40
|
+
|
41
|
+
transformed_record[transformed_key] = transformed_value
|
42
|
+
return transformed_record
|
43
|
+
|
44
|
+
def process_key(self, key: str) -> str:
|
45
|
+
key = self.normalize_key(key)
|
46
|
+
tokens = self.tokenize_key(key)
|
47
|
+
tokens = self.filter_tokens(tokens)
|
48
|
+
return self.tokens_to_snake_case(tokens)
|
49
|
+
|
50
|
+
def normalize_key(self, key: str) -> str:
|
51
|
+
return unidecode.unidecode(key)
|
52
|
+
|
53
|
+
def tokenize_key(self, key: str) -> List[str]:
|
54
|
+
tokens = []
|
55
|
+
for match in self.token_pattern.finditer(key):
|
56
|
+
token = match.group(0) if match.group("NoToken") is None else ""
|
57
|
+
tokens.append(token)
|
58
|
+
return tokens
|
59
|
+
|
60
|
+
def filter_tokens(self, tokens: List[str]) -> List[str]:
|
61
|
+
if len(tokens) >= 3:
|
62
|
+
tokens = tokens[:1] + [t for t in tokens[1:-1] if t] + tokens[-1:]
|
63
|
+
if tokens and tokens[0].isdigit():
|
64
|
+
tokens.insert(0, "")
|
65
|
+
return tokens
|
66
|
+
|
67
|
+
def tokens_to_snake_case(self, tokens: List[str]) -> str:
|
68
|
+
return "_".join(token.lower() for token in tokens)
|
@@ -262,7 +262,7 @@ class HttpClient:
|
|
262
262
|
user_backoff_handler = user_defined_backoff_handler(max_tries=max_tries, max_time=max_time)(
|
263
263
|
self._send
|
264
264
|
)
|
265
|
-
rate_limit_backoff_handler = rate_limit_default_backoff_handler()
|
265
|
+
rate_limit_backoff_handler = rate_limit_default_backoff_handler(max_tries=max_tries)
|
266
266
|
backoff_handler = http_client_default_backoff_handler(
|
267
267
|
max_tries=max_tries, max_time=max_time
|
268
268
|
)
|
@@ -472,7 +472,9 @@ class HttpClient:
|
|
472
472
|
|
473
473
|
elif retry_endlessly:
|
474
474
|
raise RateLimitBackoffException(
|
475
|
-
request=request,
|
475
|
+
request=request,
|
476
|
+
response=(response if response is not None else exc),
|
477
|
+
error_message=error_message,
|
476
478
|
)
|
477
479
|
|
478
480
|
raise DefaultBackoffException(
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: airbyte-cdk
|
3
|
-
Version: 6.
|
3
|
+
Version: 6.12.0
|
4
4
|
Summary: A framework for writing Airbyte Connectors.
|
5
5
|
Home-page: https://airbyte.com
|
6
6
|
License: MIT
|
@@ -22,6 +22,7 @@ Provides-Extra: sql
|
|
22
22
|
Provides-Extra: vector-db-based
|
23
23
|
Requires-Dist: Jinja2 (>=3.1.2,<3.2.0)
|
24
24
|
Requires-Dist: PyYAML (>=6.0.1,<7.0.0)
|
25
|
+
Requires-Dist: Unidecode (>=1.3,<2.0)
|
25
26
|
Requires-Dist: airbyte-protocol-models-dataclasses (>=0.14,<0.15)
|
26
27
|
Requires-Dist: avro (>=1.11.2,<1.12.0) ; extra == "file-based"
|
27
28
|
Requires-Dist: backoff
|
@@ -66,7 +66,7 @@ airbyte_cdk/sources/declarative/concurrent_declarative_source.py,sha256=PxP4p268
|
|
66
66
|
airbyte_cdk/sources/declarative/datetime/__init__.py,sha256=l9LG7Qm6e5r_qgqfVKnx3mXYtg1I9MmMjomVIPfU4XA,177
|
67
67
|
airbyte_cdk/sources/declarative/datetime/datetime_parser.py,sha256=SX9JjdesN1edN2WVUVMzU_ptqp2QB1OnsnjZ4mwcX7w,2579
|
68
68
|
airbyte_cdk/sources/declarative/datetime/min_max_datetime.py,sha256=0BHBtDNQZfvwM45-tY5pNlTcKAFSGGNxemoi0Jic-0E,5785
|
69
|
-
airbyte_cdk/sources/declarative/declarative_component_schema.yaml,sha256=
|
69
|
+
airbyte_cdk/sources/declarative/declarative_component_schema.yaml,sha256=Ls6VUtfX2GvJHR-hv5rs9azjAnunmr8JqZh8vi0DmU4,129264
|
70
70
|
airbyte_cdk/sources/declarative/declarative_source.py,sha256=nF7wBqFd3AQmEKAm4CnIo29CJoQL562cJGSCeL8U8bA,1531
|
71
71
|
airbyte_cdk/sources/declarative/declarative_stream.py,sha256=JRyNeOIpsFu4ztVZsN6sncqUEIqIE-bUkD2TPgbMgk0,10375
|
72
72
|
airbyte_cdk/sources/declarative/decoders/__init__.py,sha256=hNlhaB5FjNC6IfJyglj5ZJWkYD2nEAukMDmzRz5PC6o,671
|
@@ -104,14 +104,13 @@ airbyte_cdk/sources/declarative/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW
|
|
104
104
|
airbyte_cdk/sources/declarative/migrations/legacy_to_per_partition_state_migration.py,sha256=iemy3fKLczcU0-Aor7tx5jcT6DRedKMqyK7kCOp01hg,3924
|
105
105
|
airbyte_cdk/sources/declarative/migrations/state_migration.py,sha256=KWPjealMLKSMtajXgkdGgKg7EmTLR-CqqD7UIh0-eDU,794
|
106
106
|
airbyte_cdk/sources/declarative/models/__init__.py,sha256=nUFxNCiKeYRVXuZEKA7GD-lTHxsiKcQ8FitZjKhPIvE,100
|
107
|
-
airbyte_cdk/sources/declarative/models/declarative_component_schema.py,sha256=
|
107
|
+
airbyte_cdk/sources/declarative/models/declarative_component_schema.py,sha256=kESlZ8F2i2q3BMZfEhwEk0XEzxr7SWtJti6AoPsthg0,90831
|
108
108
|
airbyte_cdk/sources/declarative/parsers/__init__.py,sha256=ZnqYNxHsKCgO38IwB34RQyRMXTs4GTvlRi3ImKnIioo,61
|
109
109
|
airbyte_cdk/sources/declarative/parsers/custom_exceptions.py,sha256=Rir9_z3Kcd5Es0-LChrzk-0qubAsiK_RSEnLmK2OXm8,553
|
110
110
|
airbyte_cdk/sources/declarative/parsers/manifest_component_transformer.py,sha256=CXwTfD3wSQq3okcqwigpprbHhSURUokh4GK2OmOyKC8,9132
|
111
111
|
airbyte_cdk/sources/declarative/parsers/manifest_reference_resolver.py,sha256=IWUOdF03o-aQn0Occo1BJCxU0Pz-QILk5L67nzw2thw,6803
|
112
|
-
airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py,sha256=
|
113
|
-
airbyte_cdk/sources/declarative/partition_routers/__init__.py,sha256=
|
114
|
-
airbyte_cdk/sources/declarative/partition_routers/async_job_partition_router.py,sha256=n82J15S8bjeMZ5uROu--P3hnbQoxkY5v7RPHYx7g7ro,2929
|
112
|
+
airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py,sha256=uGh-zDTkJaSirWaB67cnoJUQKqAs-nxSHJAsQKMAcNE,105716
|
113
|
+
airbyte_cdk/sources/declarative/partition_routers/__init__.py,sha256=1NjaZoGAIefvWwj6wx-LOKIXXWS-UnBlZFnuR7y6uYA,745
|
115
114
|
airbyte_cdk/sources/declarative/partition_routers/cartesian_product_stream_slicer.py,sha256=c5cuVFM6NFkuQqG8Z5IwkBuwDrvXZN1CunUOM_L0ezg,6892
|
116
115
|
airbyte_cdk/sources/declarative/partition_routers/list_partition_router.py,sha256=t7pRdFWfFWJtQQG19c9PVeMODyO2BknRTakpM5U9N-8,4844
|
117
116
|
airbyte_cdk/sources/declarative/partition_routers/partition_router.py,sha256=YyEIzdmLd1FjbVP3QbQ2VFCLW_P-OGbVh6VpZShp54k,2218
|
@@ -158,12 +157,12 @@ airbyte_cdk/sources/declarative/resolvers/components_resolver.py,sha256=KPjKc0yb
|
|
158
157
|
airbyte_cdk/sources/declarative/resolvers/config_components_resolver.py,sha256=dz4iJV9liD_LzY_Mn4XmAStoUll60R3MIGWV4aN3pgg,5223
|
159
158
|
airbyte_cdk/sources/declarative/resolvers/http_components_resolver.py,sha256=ZA2vrHQKfXNMcH3x1iuyFOTGNzYDhUFT2qcaiOzSK0A,4271
|
160
159
|
airbyte_cdk/sources/declarative/retrievers/__init__.py,sha256=FVQpUGVwp2Gibk4gp07VmLKX5AafUlsZWFSrDpUDuJM,443
|
161
|
-
airbyte_cdk/sources/declarative/retrievers/async_retriever.py,sha256=
|
160
|
+
airbyte_cdk/sources/declarative/retrievers/async_retriever.py,sha256=WDFnjrXLz3-YEjFhmlMkWAn9AJvnZ0mk9FyC8DAhEYk,4976
|
162
161
|
airbyte_cdk/sources/declarative/retrievers/retriever.py,sha256=XPLs593Xv8c5cKMc37XzUAYmzlXd1a7eSsspM-CMuWA,1696
|
163
162
|
airbyte_cdk/sources/declarative/retrievers/simple_retriever.py,sha256=N4swGw5mfuTXJ2R7AKX18CHzizsr69pXwt5uSHLPi48,24172
|
164
163
|
airbyte_cdk/sources/declarative/schema/__init__.py,sha256=Io9vninzlEjQ2uFmWklxfwNM0cXfljtzOz5zL1OVyT4,701
|
165
164
|
airbyte_cdk/sources/declarative/schema/default_schema_loader.py,sha256=KTACrIE23a83wsm3Rd9Eb4K6-20lrGqYxTHNp9yxsso,1820
|
166
|
-
airbyte_cdk/sources/declarative/schema/dynamic_schema_loader.py,sha256=
|
165
|
+
airbyte_cdk/sources/declarative/schema/dynamic_schema_loader.py,sha256=H6A3NQ6kPPM-cUNPmdvDPc9xNzR1rQNrK95GbgCW334,8822
|
167
166
|
airbyte_cdk/sources/declarative/schema/inline_schema_loader.py,sha256=bVETE10hRsatRJq3R3BeyRR0wIoK3gcP1gcpVRQ_P5U,464
|
168
167
|
airbyte_cdk/sources/declarative/schema/json_file_schema_loader.py,sha256=5Wl-fqW-pVf_dxJ4yGHMAFfC4JjKHYJhqFJT1xA57F4,4177
|
169
168
|
airbyte_cdk/sources/declarative/schema/schema_loader.py,sha256=kjt8v0N5wWKA5zyLnrDLxf1PJKdUqvQq2RVnAOAzNSY,379
|
@@ -174,7 +173,9 @@ airbyte_cdk/sources/declarative/stream_slicers/declarative_partition_generator.p
|
|
174
173
|
airbyte_cdk/sources/declarative/stream_slicers/stream_slicer.py,sha256=SOkIPBi2Wu7yxIvA15yFzUAB95a3IzA8LPq5DEqHQQc,725
|
175
174
|
airbyte_cdk/sources/declarative/transformations/__init__.py,sha256=CPJ8TlMpiUmvG3624VYu_NfTzxwKcfBjM2Q2wJ7fkSA,919
|
176
175
|
airbyte_cdk/sources/declarative/transformations/add_fields.py,sha256=r4YdAuAk2bQtNWJMztIIy2CC-NglD9NeK1s1TeO9wkw,5027
|
176
|
+
airbyte_cdk/sources/declarative/transformations/flatten_fields.py,sha256=ti9fLVk-EpMeDY7ImduvQq1YGounLYmH9dHzp7MIRxk,1703
|
177
177
|
airbyte_cdk/sources/declarative/transformations/keys_to_lower_transformation.py,sha256=RTs5KX4V3hM7A6QN1WlGF21YccTIyNH6qQI9IMb__hw,670
|
178
|
+
airbyte_cdk/sources/declarative/transformations/keys_to_snake_transformation.py,sha256=43zwe6_F5ba5C4eY0RgXxPz7ndPKZfXGChHepFn-2lk,2263
|
178
179
|
airbyte_cdk/sources/declarative/transformations/remove_fields.py,sha256=EwUP0SZ2p4GRJ6Q8CUzlz9dcUeEidEFDlI2IBye2tlc,2745
|
179
180
|
airbyte_cdk/sources/declarative/transformations/transformation.py,sha256=4sXtx9cNY2EHUPq-xHvDs8GQEBUy3Eo6TkRLKHPXx68,1161
|
180
181
|
airbyte_cdk/sources/declarative/types.py,sha256=yqx0xlZv_76tkC7fqJKefmvl4GJJ8mXbeddwVV8XRJU,778
|
@@ -279,7 +280,7 @@ airbyte_cdk/sources/streams/http/error_handlers/json_error_message_parser.py,sha
|
|
279
280
|
airbyte_cdk/sources/streams/http/error_handlers/response_models.py,sha256=xGIVELBFY0TmH9aUq1ikoqJz8oHLr6di2JLvKWVEO-s,2236
|
280
281
|
airbyte_cdk/sources/streams/http/exceptions.py,sha256=njC7MlMJoFYcSGz4mIp6-bqLFTr6vC8ej25X0oSeyjE,1824
|
281
282
|
airbyte_cdk/sources/streams/http/http.py,sha256=JAMpiTdS9HFNOlwayWNvQdxoqs2rpW9wdYlhFHv_1Q4,28496
|
282
|
-
airbyte_cdk/sources/streams/http/http_client.py,sha256=
|
283
|
+
airbyte_cdk/sources/streams/http/http_client.py,sha256=tDE0ROtxjGMVphvsw8INvGMtZ97hIF-v47pZ3jIyiwc,23011
|
283
284
|
airbyte_cdk/sources/streams/http/rate_limiting.py,sha256=IwdjrHKUnU97XO4qONgYRv4YYW51xQ8SJm4WLafXDB8,6351
|
284
285
|
airbyte_cdk/sources/streams/http/requests_native_auth/__init__.py,sha256=RN0D3nOX1xLgwEwKWu6pkGy3XqBFzKSNZ8Lf6umU2eY,413
|
285
286
|
airbyte_cdk/sources/streams/http/requests_native_auth/abstract_oauth.py,sha256=nxI94yJ3bGfpDO8RR3QvOJ-PSW0n9CElSAkgl5ae80Y,10321
|
@@ -337,8 +338,8 @@ airbyte_cdk/utils/slice_hasher.py,sha256=-pHexlNYoWYPnXNH-M7HEbjmeJe9Zk7SJijdQ7d
|
|
337
338
|
airbyte_cdk/utils/spec_schema_transformations.py,sha256=-5HTuNsnDBAhj-oLeQXwpTGA0HdcjFOf2zTEMUTTg_Y,816
|
338
339
|
airbyte_cdk/utils/stream_status_utils.py,sha256=ZmBoiy5HVbUEHAMrUONxZvxnvfV9CesmQJLDTAIWnWw,1171
|
339
340
|
airbyte_cdk/utils/traced_exception.py,sha256=C8uIBuCL_E4WnBAOPSxBicD06JAldoN9fGsQDp463OY,6292
|
340
|
-
airbyte_cdk-6.
|
341
|
-
airbyte_cdk-6.
|
342
|
-
airbyte_cdk-6.
|
343
|
-
airbyte_cdk-6.
|
344
|
-
airbyte_cdk-6.
|
341
|
+
airbyte_cdk-6.12.0.dist-info/LICENSE.txt,sha256=Wfe61S4BaGPj404v8lrAbvhjYR68SHlkzeYrg3_bbuM,1051
|
342
|
+
airbyte_cdk-6.12.0.dist-info/METADATA,sha256=3KZ1_QqdXybMOsKxD9zYe1w0QhREO_XsDc0Nm_yPBTo,5988
|
343
|
+
airbyte_cdk-6.12.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
344
|
+
airbyte_cdk-6.12.0.dist-info/entry_points.txt,sha256=fj-e3PAQvsxsQzyyq8UkG1k8spunWnD4BAH2AwlR6NM,95
|
345
|
+
airbyte_cdk-6.12.0.dist-info/RECORD,,
|
@@ -1,65 +0,0 @@
|
|
1
|
-
# Copyright (c) 2024 Airbyte, Inc., all rights reserved.
|
2
|
-
|
3
|
-
from dataclasses import InitVar, dataclass, field
|
4
|
-
from typing import Any, Callable, Iterable, Mapping, Optional
|
5
|
-
|
6
|
-
from airbyte_cdk.models import FailureType
|
7
|
-
from airbyte_cdk.sources.declarative.async_job.job_orchestrator import (
|
8
|
-
AsyncJobOrchestrator,
|
9
|
-
AsyncPartition,
|
10
|
-
)
|
11
|
-
from airbyte_cdk.sources.declarative.partition_routers.single_partition_router import (
|
12
|
-
SinglePartitionRouter,
|
13
|
-
)
|
14
|
-
from airbyte_cdk.sources.streams.concurrent.partitions.stream_slicer import StreamSlicer
|
15
|
-
from airbyte_cdk.sources.types import Config, StreamSlice
|
16
|
-
from airbyte_cdk.utils.traced_exception import AirbyteTracedException
|
17
|
-
|
18
|
-
|
19
|
-
@dataclass
|
20
|
-
class AsyncJobPartitionRouter(StreamSlicer):
|
21
|
-
"""
|
22
|
-
Partition router that creates async jobs in a source API, periodically polls for job
|
23
|
-
completion, and supplies the completed job URL locations as stream slices so that
|
24
|
-
records can be extracted.
|
25
|
-
"""
|
26
|
-
|
27
|
-
config: Config
|
28
|
-
parameters: InitVar[Mapping[str, Any]]
|
29
|
-
job_orchestrator_factory: Callable[[Iterable[StreamSlice]], AsyncJobOrchestrator]
|
30
|
-
stream_slicer: StreamSlicer = field(
|
31
|
-
default_factory=lambda: SinglePartitionRouter(parameters={})
|
32
|
-
)
|
33
|
-
|
34
|
-
def __post_init__(self, parameters: Mapping[str, Any]) -> None:
|
35
|
-
self._job_orchestrator_factory = self.job_orchestrator_factory
|
36
|
-
self._job_orchestrator: Optional[AsyncJobOrchestrator] = None
|
37
|
-
self._parameters = parameters
|
38
|
-
|
39
|
-
def stream_slices(self) -> Iterable[StreamSlice]:
|
40
|
-
slices = self.stream_slicer.stream_slices()
|
41
|
-
self._job_orchestrator = self._job_orchestrator_factory(slices)
|
42
|
-
|
43
|
-
for completed_partition in self._job_orchestrator.create_and_get_completed_partitions():
|
44
|
-
yield StreamSlice(
|
45
|
-
partition=dict(completed_partition.stream_slice.partition)
|
46
|
-
| {"partition": completed_partition},
|
47
|
-
cursor_slice=completed_partition.stream_slice.cursor_slice,
|
48
|
-
)
|
49
|
-
|
50
|
-
def fetch_records(self, partition: AsyncPartition) -> Iterable[Mapping[str, Any]]:
|
51
|
-
"""
|
52
|
-
This method of fetching records extends beyond what a PartitionRouter/StreamSlicer should
|
53
|
-
be responsible for. However, this was added in because the JobOrchestrator is required to
|
54
|
-
retrieve records. And without defining fetch_records() on this class, we're stuck with either
|
55
|
-
passing the JobOrchestrator to the AsyncRetriever or storing it on multiple classes.
|
56
|
-
"""
|
57
|
-
|
58
|
-
if not self._job_orchestrator:
|
59
|
-
raise AirbyteTracedException(
|
60
|
-
message="Invalid state within AsyncJobRetriever. Please contact Airbyte Support",
|
61
|
-
internal_message="AsyncPartitionRepository is expected to be accessed only after `stream_slices`",
|
62
|
-
failure_type=FailureType.system_error,
|
63
|
-
)
|
64
|
-
|
65
|
-
return self._job_orchestrator.fetch_records(partition=partition)
|
File without changes
|
File without changes
|
File without changes
|