airbyte-cdk 6.9.0__py3-none-any.whl → 6.9.0.dev0__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/concurrent_declarative_source.py +28 -18
- airbyte_cdk/sources/declarative/declarative_component_schema.yaml +86 -0
- airbyte_cdk/sources/declarative/models/declarative_component_schema.py +42 -4
- airbyte_cdk/sources/declarative/parsers/manifest_component_transformer.py +4 -0
- airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py +72 -0
- airbyte_cdk/sources/declarative/schema/__init__.py +2 -1
- airbyte_cdk/sources/declarative/schema/dynamic_schema_loader.py +219 -0
- {airbyte_cdk-6.9.0.dist-info → airbyte_cdk-6.9.0.dev0.dist-info}/METADATA +4 -1
- {airbyte_cdk-6.9.0.dist-info → airbyte_cdk-6.9.0.dev0.dist-info}/RECORD +12 -11
- {airbyte_cdk-6.9.0.dist-info → airbyte_cdk-6.9.0.dev0.dist-info}/LICENSE.txt +0 -0
- {airbyte_cdk-6.9.0.dist-info → airbyte_cdk-6.9.0.dev0.dist-info}/WHEEL +0 -0
- {airbyte_cdk-6.9.0.dist-info → airbyte_cdk-6.9.0.dev0.dist-info}/entry_points.txt +0 -0
@@ -86,10 +86,23 @@ class ConcurrentDeclarativeSource(ManifestDeclarativeSource, Generic[TState]):
|
|
86
86
|
component_factory=component_factory,
|
87
87
|
)
|
88
88
|
|
89
|
-
# todo: We could remove state from initialization. Now that streams are grouped during the read(), a source
|
90
|
-
# no longer needs to store the original incoming state. But maybe there's an edge case?
|
91
89
|
self._state = state
|
92
90
|
|
91
|
+
self._concurrent_streams: Optional[List[AbstractStream]]
|
92
|
+
self._synchronous_streams: Optional[List[Stream]]
|
93
|
+
|
94
|
+
# If the connector command was SPEC, there is no incoming config, and we cannot instantiate streams because
|
95
|
+
# they might depend on it. Ideally we want to have a static method on this class to get the spec without
|
96
|
+
# any other arguments, but the existing entrypoint.py isn't designed to support this. Just noting this
|
97
|
+
# for our future improvements to the CDK.
|
98
|
+
if config:
|
99
|
+
self._concurrent_streams, self._synchronous_streams = self._group_streams(
|
100
|
+
config=config or {}
|
101
|
+
)
|
102
|
+
else:
|
103
|
+
self._concurrent_streams = None
|
104
|
+
self._synchronous_streams = None
|
105
|
+
|
93
106
|
concurrency_level_from_manifest = self._source_config.get("concurrency_level")
|
94
107
|
if concurrency_level_from_manifest:
|
95
108
|
concurrency_level_component = self._constructor.create_component(
|
@@ -123,20 +136,17 @@ class ConcurrentDeclarativeSource(ManifestDeclarativeSource, Generic[TState]):
|
|
123
136
|
logger: logging.Logger,
|
124
137
|
config: Mapping[str, Any],
|
125
138
|
catalog: ConfiguredAirbyteCatalog,
|
126
|
-
state: Optional[List[AirbyteStateMessage]] = None,
|
139
|
+
state: Optional[Union[List[AirbyteStateMessage]]] = None,
|
127
140
|
) -> Iterator[AirbyteMessage]:
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
# the concurrent streams must be saved so that they can be removed from the catalog before starting
|
132
|
-
# synchronous streams
|
133
|
-
if len(concurrent_streams) > 0:
|
141
|
+
# ConcurrentReadProcessor pops streams that are finished being read so before syncing, the names of the concurrent
|
142
|
+
# streams must be saved so that they can be removed from the catalog before starting synchronous streams
|
143
|
+
if self._concurrent_streams:
|
134
144
|
concurrent_stream_names = set(
|
135
|
-
[concurrent_stream.name for concurrent_stream in
|
145
|
+
[concurrent_stream.name for concurrent_stream in self._concurrent_streams]
|
136
146
|
)
|
137
147
|
|
138
148
|
selected_concurrent_streams = self._select_streams(
|
139
|
-
streams=
|
149
|
+
streams=self._concurrent_streams, configured_catalog=catalog
|
140
150
|
)
|
141
151
|
# It would appear that passing in an empty set of streams causes an infinite loop in ConcurrentReadProcessor.
|
142
152
|
# This is also evident in concurrent_source_adapter.py so I'll leave this out of scope to fix for now
|
@@ -155,7 +165,8 @@ class ConcurrentDeclarativeSource(ManifestDeclarativeSource, Generic[TState]):
|
|
155
165
|
yield from super().read(logger, config, filtered_catalog, state)
|
156
166
|
|
157
167
|
def discover(self, logger: logging.Logger, config: Mapping[str, Any]) -> AirbyteCatalog:
|
158
|
-
concurrent_streams
|
168
|
+
concurrent_streams = self._concurrent_streams or []
|
169
|
+
synchronous_streams = self._synchronous_streams or []
|
159
170
|
return AirbyteCatalog(
|
160
171
|
streams=[
|
161
172
|
stream.as_airbyte_stream() for stream in concurrent_streams + synchronous_streams
|
@@ -195,7 +206,7 @@ class ConcurrentDeclarativeSource(ManifestDeclarativeSource, Generic[TState]):
|
|
195
206
|
# so we need to treat them as synchronous
|
196
207
|
if (
|
197
208
|
isinstance(declarative_stream, DeclarativeStream)
|
198
|
-
and name_to_stream_mapping[declarative_stream.name]
|
209
|
+
and name_to_stream_mapping[declarative_stream.name].get("retriever")["type"]
|
199
210
|
== "SimpleRetriever"
|
200
211
|
):
|
201
212
|
incremental_sync_component_definition = name_to_stream_mapping[
|
@@ -204,7 +215,7 @@ class ConcurrentDeclarativeSource(ManifestDeclarativeSource, Generic[TState]):
|
|
204
215
|
|
205
216
|
partition_router_component_definition = (
|
206
217
|
name_to_stream_mapping[declarative_stream.name]
|
207
|
-
.get("retriever"
|
218
|
+
.get("retriever")
|
208
219
|
.get("partition_router")
|
209
220
|
)
|
210
221
|
is_without_partition_router_or_cursor = not bool(
|
@@ -226,7 +237,7 @@ class ConcurrentDeclarativeSource(ManifestDeclarativeSource, Generic[TState]):
|
|
226
237
|
cursor = self._constructor.create_concurrent_cursor_from_datetime_based_cursor(
|
227
238
|
state_manager=state_manager,
|
228
239
|
model_type=DatetimeBasedCursorModel,
|
229
|
-
component_definition=incremental_sync_component_definition,
|
240
|
+
component_definition=incremental_sync_component_definition,
|
230
241
|
stream_name=declarative_stream.name,
|
231
242
|
stream_namespace=declarative_stream.namespace,
|
232
243
|
config=config or {},
|
@@ -309,11 +320,10 @@ class ConcurrentDeclarativeSource(ManifestDeclarativeSource, Generic[TState]):
|
|
309
320
|
def _is_datetime_incremental_without_partition_routing(
|
310
321
|
self,
|
311
322
|
declarative_stream: DeclarativeStream,
|
312
|
-
incremental_sync_component_definition: Mapping[str, Any]
|
323
|
+
incremental_sync_component_definition: Mapping[str, Any],
|
313
324
|
) -> bool:
|
314
325
|
return (
|
315
|
-
incremental_sync_component_definition
|
316
|
-
and bool(incremental_sync_component_definition)
|
326
|
+
bool(incremental_sync_component_definition)
|
317
327
|
and incremental_sync_component_definition.get("type", "")
|
318
328
|
== DatetimeBasedCursorModel.__name__
|
319
329
|
and self._stream_supports_concurrent_partition_processing(
|
@@ -1684,6 +1684,92 @@ definitions:
|
|
1684
1684
|
$parameters:
|
1685
1685
|
type: object
|
1686
1686
|
additionalProperties: true
|
1687
|
+
TypesMap:
|
1688
|
+
title: Types Map
|
1689
|
+
description: (This component is experimental. Use at your own risk.) Represents a mapping between a current type and its corresponding target type.
|
1690
|
+
type: object
|
1691
|
+
required:
|
1692
|
+
- target_type
|
1693
|
+
- current_type
|
1694
|
+
properties:
|
1695
|
+
target_type:
|
1696
|
+
anyOf:
|
1697
|
+
- type: string
|
1698
|
+
- type: array
|
1699
|
+
items:
|
1700
|
+
type: string
|
1701
|
+
current_type:
|
1702
|
+
anyOf:
|
1703
|
+
- type: string
|
1704
|
+
- type: array
|
1705
|
+
items:
|
1706
|
+
type: string
|
1707
|
+
SchemaTypeIdentifier:
|
1708
|
+
title: Schema Type Identifier
|
1709
|
+
description: (This component is experimental. Use at your own risk.) Identifies schema details for dynamic schema extraction and processing.
|
1710
|
+
type: object
|
1711
|
+
required:
|
1712
|
+
- key_pointer
|
1713
|
+
properties:
|
1714
|
+
type:
|
1715
|
+
type: string
|
1716
|
+
enum: [SchemaTypeIdentifier]
|
1717
|
+
schema_pointer:
|
1718
|
+
title: Schema Path
|
1719
|
+
description: List of nested fields defining the schema field path to extract. Defaults to [].
|
1720
|
+
type: array
|
1721
|
+
default: []
|
1722
|
+
items:
|
1723
|
+
- type: string
|
1724
|
+
interpolation_content:
|
1725
|
+
- config
|
1726
|
+
key_pointer:
|
1727
|
+
title: Key Path
|
1728
|
+
description: List of potentially nested fields describing the full path of the field key to extract.
|
1729
|
+
type: array
|
1730
|
+
items:
|
1731
|
+
- type: string
|
1732
|
+
interpolation_content:
|
1733
|
+
- config
|
1734
|
+
type_pointer:
|
1735
|
+
title: Type Path
|
1736
|
+
description: List of potentially nested fields describing the full path of the field type to extract.
|
1737
|
+
type: array
|
1738
|
+
items:
|
1739
|
+
- type: string
|
1740
|
+
interpolation_content:
|
1741
|
+
- config
|
1742
|
+
types_mapping:
|
1743
|
+
type: array
|
1744
|
+
items:
|
1745
|
+
- "$ref": "#/definitions/TypesMap"
|
1746
|
+
$parameters:
|
1747
|
+
type: object
|
1748
|
+
additionalProperties: true
|
1749
|
+
DynamicSchemaLoader:
|
1750
|
+
title: Dynamic Schema Loader
|
1751
|
+
description: (This component is experimental. Use at your own risk.) Loads a schema by extracting data from retrieved records.
|
1752
|
+
type: object
|
1753
|
+
required:
|
1754
|
+
- type
|
1755
|
+
- retriever
|
1756
|
+
- schema_type_identifier
|
1757
|
+
properties:
|
1758
|
+
type:
|
1759
|
+
type: string
|
1760
|
+
enum: [DynamicSchemaLoader]
|
1761
|
+
retriever:
|
1762
|
+
title: Retriever
|
1763
|
+
description: Component used to coordinate how records are extracted across stream slices and request pages.
|
1764
|
+
anyOf:
|
1765
|
+
- "$ref": "#/definitions/AsyncRetriever"
|
1766
|
+
- "$ref": "#/definitions/CustomRetriever"
|
1767
|
+
- "$ref": "#/definitions/SimpleRetriever"
|
1768
|
+
schema_type_identifier:
|
1769
|
+
"$ref": "#/definitions/SchemaTypeIdentifier"
|
1770
|
+
$parameters:
|
1771
|
+
type: object
|
1772
|
+
additionalProperties: true
|
1687
1773
|
InlineSchemaLoader:
|
1688
1774
|
title: Inline Schema Loader
|
1689
1775
|
description: Loads a schema that is defined directly in the manifest file.
|
@@ -650,6 +650,32 @@ class HttpResponseFilter(BaseModel):
|
|
650
650
|
parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
|
651
651
|
|
652
652
|
|
653
|
+
class TypesMap(BaseModel):
|
654
|
+
target_type: Union[str, List[str]]
|
655
|
+
current_type: Union[str, List[str]]
|
656
|
+
|
657
|
+
|
658
|
+
class SchemaTypeIdentifier(BaseModel):
|
659
|
+
type: Optional[Literal["SchemaTypeIdentifier"]] = None
|
660
|
+
schema_pointer: Optional[List[str]] = Field(
|
661
|
+
[],
|
662
|
+
description="List of nested fields defining the schema field path to extract. Defaults to [].",
|
663
|
+
title="Schema Path",
|
664
|
+
)
|
665
|
+
key_pointer: List[str] = Field(
|
666
|
+
...,
|
667
|
+
description="List of potentially nested fields describing the full path of the field key to extract.",
|
668
|
+
title="Key Path",
|
669
|
+
)
|
670
|
+
type_pointer: Optional[List[str]] = Field(
|
671
|
+
None,
|
672
|
+
description="List of potentially nested fields describing the full path of the field type to extract.",
|
673
|
+
title="Type Path",
|
674
|
+
)
|
675
|
+
types_mapping: Optional[List[TypesMap]] = None
|
676
|
+
parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
|
677
|
+
|
678
|
+
|
653
679
|
class InlineSchemaLoader(BaseModel):
|
654
680
|
type: Literal["InlineSchemaLoader"]
|
655
681
|
schema_: Optional[Dict[str, Any]] = Field(
|
@@ -822,13 +848,13 @@ class OauthConnectorInputSpecification(BaseModel):
|
|
822
848
|
)
|
823
849
|
extract_output: List[str] = Field(
|
824
850
|
...,
|
825
|
-
description="The DeclarativeOAuth Specific list of strings to indicate which keys should be extracted and returned back to the input config.
|
851
|
+
description="The DeclarativeOAuth Specific list of strings to indicate which keys should be extracted and returned back to the input config.",
|
826
852
|
examples=[{"extract_output": ["access_token", "refresh_token", "other_field"]}],
|
827
853
|
title="DeclarativeOAuth Extract Output",
|
828
854
|
)
|
829
855
|
state: Optional[State] = Field(
|
830
856
|
None,
|
831
|
-
description="The DeclarativeOAuth Specific object to provide the criteria of how the `state` query param should be constructed,\nincluding length and complexity.
|
857
|
+
description="The DeclarativeOAuth Specific object to provide the criteria of how the `state` query param should be constructed,\nincluding length and complexity.",
|
832
858
|
examples=[{"state": {"min": 7, "max": 128}}],
|
833
859
|
title="(Optional) DeclarativeOAuth Configurable State Query Param",
|
834
860
|
)
|
@@ -852,13 +878,13 @@ class OauthConnectorInputSpecification(BaseModel):
|
|
852
878
|
)
|
853
879
|
state_key: Optional[str] = Field(
|
854
880
|
None,
|
855
|
-
description="The DeclarativeOAuth Specific optional override to provide the custom `state` key name, if required by data-provider.
|
881
|
+
description="The DeclarativeOAuth Specific optional override to provide the custom `state` key name, if required by data-provider.",
|
856
882
|
examples=[{"state_key": "my_custom_state_key_key_name"}],
|
857
883
|
title="(Optional) DeclarativeOAuth State Key Override",
|
858
884
|
)
|
859
885
|
auth_code_key: Optional[str] = Field(
|
860
886
|
None,
|
861
|
-
description="The DeclarativeOAuth Specific optional override to provide the custom `code` key name to something like `auth_code` or `custom_auth_code`, if required by data-provider.
|
887
|
+
description="The DeclarativeOAuth Specific optional override to provide the custom `code` key name to something like `auth_code` or `custom_auth_code`, if required by data-provider.",
|
862
888
|
examples=[{"auth_code_key": "my_custom_auth_code_key_name"}],
|
863
889
|
title="(Optional) DeclarativeOAuth Auth Code Key Override",
|
864
890
|
)
|
@@ -1774,6 +1800,17 @@ class HttpRequester(BaseModel):
|
|
1774
1800
|
parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
|
1775
1801
|
|
1776
1802
|
|
1803
|
+
class DynamicSchemaLoader(BaseModel):
|
1804
|
+
type: Literal["DynamicSchemaLoader"]
|
1805
|
+
retriever: Union[AsyncRetriever, CustomRetriever, SimpleRetriever] = Field(
|
1806
|
+
...,
|
1807
|
+
description="Component used to coordinate how records are extracted across stream slices and request pages.",
|
1808
|
+
title="Retriever",
|
1809
|
+
)
|
1810
|
+
schema_type_identifier: SchemaTypeIdentifier
|
1811
|
+
parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
|
1812
|
+
|
1813
|
+
|
1777
1814
|
class ParentStreamConfig(BaseModel):
|
1778
1815
|
type: Literal["ParentStreamConfig"]
|
1779
1816
|
parent_key: str = Field(
|
@@ -1981,5 +2018,6 @@ DeclarativeSource2.update_forward_refs()
|
|
1981
2018
|
SelectiveAuthenticator.update_forward_refs()
|
1982
2019
|
DeclarativeStream.update_forward_refs()
|
1983
2020
|
SessionTokenAuthenticator.update_forward_refs()
|
2021
|
+
DynamicSchemaLoader.update_forward_refs()
|
1984
2022
|
SimpleRetriever.update_forward_refs()
|
1985
2023
|
AsyncRetriever.update_forward_refs()
|
@@ -64,6 +64,10 @@ DEFAULT_MODEL_TYPES: Mapping[str, str] = {
|
|
64
64
|
"AddFields.fields": "AddedFieldDefinition",
|
65
65
|
# CustomPartitionRouter
|
66
66
|
"CustomPartitionRouter.parent_stream_configs": "ParentStreamConfig",
|
67
|
+
# DynamicSchemaLoader
|
68
|
+
"DynamicSchemaLoader.retriever": "SimpleRetriever",
|
69
|
+
# SchemaTypeIdentifier
|
70
|
+
"SchemaTypeIdentifier.types_map": "TypesMap",
|
67
71
|
}
|
68
72
|
|
69
73
|
# We retain a separate registry for custom components to automatically insert the type if it is missing. This is intended to
|
@@ -188,6 +188,9 @@ from airbyte_cdk.sources.declarative.models.declarative_component_schema import
|
|
188
188
|
from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
|
189
189
|
DpathExtractor as DpathExtractorModel,
|
190
190
|
)
|
191
|
+
from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
|
192
|
+
DynamicSchemaLoader as DynamicSchemaLoaderModel,
|
193
|
+
)
|
191
194
|
from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
|
192
195
|
ExponentialBackoffStrategy as ExponentialBackoffStrategyModel,
|
193
196
|
)
|
@@ -278,6 +281,9 @@ from airbyte_cdk.sources.declarative.models.declarative_component_schema import
|
|
278
281
|
from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
|
279
282
|
ResponseToFileExtractor as ResponseToFileExtractorModel,
|
280
283
|
)
|
284
|
+
from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
|
285
|
+
SchemaTypeIdentifier as SchemaTypeIdentifierModel,
|
286
|
+
)
|
281
287
|
from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
|
282
288
|
SelectiveAuthenticator as SelectiveAuthenticatorModel,
|
283
289
|
)
|
@@ -291,6 +297,9 @@ from airbyte_cdk.sources.declarative.models.declarative_component_schema import
|
|
291
297
|
from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
|
292
298
|
SubstreamPartitionRouter as SubstreamPartitionRouterModel,
|
293
299
|
)
|
300
|
+
from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
|
301
|
+
TypesMap as TypesMapModel,
|
302
|
+
)
|
294
303
|
from airbyte_cdk.sources.declarative.models.declarative_component_schema import ValueType
|
295
304
|
from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
|
296
305
|
WaitTimeFromHeader as WaitTimeFromHeaderModel,
|
@@ -356,8 +365,11 @@ from airbyte_cdk.sources.declarative.retrievers import (
|
|
356
365
|
)
|
357
366
|
from airbyte_cdk.sources.declarative.schema import (
|
358
367
|
DefaultSchemaLoader,
|
368
|
+
DynamicSchemaLoader,
|
359
369
|
InlineSchemaLoader,
|
360
370
|
JsonFileSchemaLoader,
|
371
|
+
SchemaTypeIdentifier,
|
372
|
+
TypesMap,
|
361
373
|
)
|
362
374
|
from airbyte_cdk.sources.declarative.spec import Spec
|
363
375
|
from airbyte_cdk.sources.declarative.stream_slicers import StreamSlicer
|
@@ -455,6 +467,9 @@ class ModelToComponentFactory:
|
|
455
467
|
IterableDecoderModel: self.create_iterable_decoder,
|
456
468
|
XmlDecoderModel: self.create_xml_decoder,
|
457
469
|
JsonFileSchemaLoaderModel: self.create_json_file_schema_loader,
|
470
|
+
DynamicSchemaLoaderModel: self.create_dynamic_schema_loader,
|
471
|
+
SchemaTypeIdentifierModel: self.create_schema_type_identifier,
|
472
|
+
TypesMapModel: self.create_types_map,
|
458
473
|
JwtAuthenticatorModel: self.create_jwt_authenticator,
|
459
474
|
LegacyToPerPartitionStateMigrationModel: self.create_legacy_to_per_partition_state_migration,
|
460
475
|
ListPartitionRouterModel: self.create_list_partition_router,
|
@@ -1574,6 +1589,63 @@ class ModelToComponentFactory:
|
|
1574
1589
|
) -> InlineSchemaLoader:
|
1575
1590
|
return InlineSchemaLoader(schema=model.schema_ or {}, parameters={})
|
1576
1591
|
|
1592
|
+
@staticmethod
|
1593
|
+
def create_types_map(model: TypesMapModel, **kwargs: Any) -> TypesMap:
|
1594
|
+
return TypesMap(target_type=model.target_type, current_type=model.current_type)
|
1595
|
+
|
1596
|
+
def create_schema_type_identifier(
|
1597
|
+
self, model: SchemaTypeIdentifierModel, config: Config, **kwargs: Any
|
1598
|
+
) -> SchemaTypeIdentifier:
|
1599
|
+
types_mapping = []
|
1600
|
+
if model.types_mapping:
|
1601
|
+
types_mapping.extend(
|
1602
|
+
[
|
1603
|
+
self._create_component_from_model(types_map, config=config)
|
1604
|
+
for types_map in model.types_mapping
|
1605
|
+
]
|
1606
|
+
)
|
1607
|
+
model_schema_pointer: List[Union[InterpolatedString, str]] = (
|
1608
|
+
[x for x in model.schema_pointer] if model.schema_pointer else []
|
1609
|
+
)
|
1610
|
+
model_key_pointer: List[Union[InterpolatedString, str]] = [x for x in model.key_pointer]
|
1611
|
+
model_type_pointer: Optional[List[Union[InterpolatedString, str]]] = (
|
1612
|
+
[x for x in model.type_pointer] if model.type_pointer else None
|
1613
|
+
)
|
1614
|
+
|
1615
|
+
return SchemaTypeIdentifier(
|
1616
|
+
schema_pointer=model_schema_pointer,
|
1617
|
+
key_pointer=model_key_pointer,
|
1618
|
+
type_pointer=model_type_pointer,
|
1619
|
+
types_mapping=types_mapping,
|
1620
|
+
parameters=model.parameters or {},
|
1621
|
+
)
|
1622
|
+
|
1623
|
+
def create_dynamic_schema_loader(
|
1624
|
+
self, model: DynamicSchemaLoaderModel, config: Config, **kwargs: Any
|
1625
|
+
) -> DynamicSchemaLoader:
|
1626
|
+
stream_slicer = self._build_stream_slicer_from_partition_router(model.retriever, config)
|
1627
|
+
combined_slicers = self._build_resumable_cursor_from_paginator(
|
1628
|
+
model.retriever, stream_slicer
|
1629
|
+
)
|
1630
|
+
|
1631
|
+
retriever = self._create_component_from_model(
|
1632
|
+
model=model.retriever,
|
1633
|
+
config=config,
|
1634
|
+
name="",
|
1635
|
+
primary_key=None,
|
1636
|
+
stream_slicer=combined_slicers,
|
1637
|
+
transformations=[],
|
1638
|
+
)
|
1639
|
+
schema_type_identifier = self._create_component_from_model(
|
1640
|
+
model.schema_type_identifier, config=config, parameters=model.parameters or {}
|
1641
|
+
)
|
1642
|
+
return DynamicSchemaLoader(
|
1643
|
+
retriever=retriever,
|
1644
|
+
config=config,
|
1645
|
+
schema_type_identifier=schema_type_identifier,
|
1646
|
+
parameters=model.parameters or {},
|
1647
|
+
)
|
1648
|
+
|
1577
1649
|
@staticmethod
|
1578
1650
|
def create_json_decoder(model: JsonDecoderModel, config: Config, **kwargs: Any) -> JsonDecoder:
|
1579
1651
|
return JsonDecoder(parameters={})
|
@@ -6,5 +6,6 @@ from airbyte_cdk.sources.declarative.schema.default_schema_loader import Default
|
|
6
6
|
from airbyte_cdk.sources.declarative.schema.inline_schema_loader import InlineSchemaLoader
|
7
7
|
from airbyte_cdk.sources.declarative.schema.json_file_schema_loader import JsonFileSchemaLoader
|
8
8
|
from airbyte_cdk.sources.declarative.schema.schema_loader import SchemaLoader
|
9
|
+
from airbyte_cdk.sources.declarative.schema.dynamic_schema_loader import DynamicSchemaLoader, TypesMap, SchemaTypeIdentifier
|
9
10
|
|
10
|
-
__all__ = ["JsonFileSchemaLoader", "DefaultSchemaLoader", "SchemaLoader", "InlineSchemaLoader"]
|
11
|
+
__all__ = ["JsonFileSchemaLoader", "DefaultSchemaLoader", "SchemaLoader", "InlineSchemaLoader", "DynamicSchemaLoader", "TypesMap", "SchemaTypeIdentifier"]
|
@@ -0,0 +1,219 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2024 Airbyte, Inc., all rights reserved.
|
3
|
+
#
|
4
|
+
|
5
|
+
|
6
|
+
from copy import deepcopy
|
7
|
+
from dataclasses import InitVar, dataclass
|
8
|
+
from typing import Any, List, Mapping, MutableMapping, Optional, Union
|
9
|
+
|
10
|
+
import dpath
|
11
|
+
from typing_extensions import deprecated
|
12
|
+
|
13
|
+
from airbyte_cdk.sources.declarative.interpolation.interpolated_string import InterpolatedString
|
14
|
+
from airbyte_cdk.sources.declarative.retrievers.retriever import Retriever
|
15
|
+
from airbyte_cdk.sources.declarative.schema.schema_loader import SchemaLoader
|
16
|
+
from airbyte_cdk.sources.source import ExperimentalClassWarning
|
17
|
+
from airbyte_cdk.sources.types import Config
|
18
|
+
|
19
|
+
AIRBYTE_DATA_TYPES: Mapping[str, Mapping[str, Any]] = {
|
20
|
+
"string": {"type": ["null", "string"]},
|
21
|
+
"boolean": {"type": ["null", "boolean"]},
|
22
|
+
"date": {"type": ["null", "string"], "format": "date"},
|
23
|
+
"timestamp_without_timezone": {
|
24
|
+
"type": ["null", "string"],
|
25
|
+
"format": "date-time",
|
26
|
+
"airbyte_type": "timestamp_without_timezone",
|
27
|
+
},
|
28
|
+
"timestamp_with_timezone": {"type": ["null", "string"], "format": "date-time"},
|
29
|
+
"time_without_timezone": {
|
30
|
+
"type": ["null", "string"],
|
31
|
+
"format": "time",
|
32
|
+
"airbyte_type": "time_without_timezone",
|
33
|
+
},
|
34
|
+
"time_with_timezone": {
|
35
|
+
"type": ["null", "string"],
|
36
|
+
"format": "time",
|
37
|
+
"airbyte_type": "time_with_timezone",
|
38
|
+
},
|
39
|
+
"integer": {"type": ["null", "integer"]},
|
40
|
+
"number": {"type": ["null", "number"]},
|
41
|
+
"array": {"type": ["null", "array"]},
|
42
|
+
"object": {"type": ["null", "object"]},
|
43
|
+
}
|
44
|
+
|
45
|
+
|
46
|
+
@deprecated("This class is experimental. Use at your own risk.", category=ExperimentalClassWarning)
|
47
|
+
@dataclass(frozen=True)
|
48
|
+
class TypesMap:
|
49
|
+
"""
|
50
|
+
Represents a mapping between a current type and its corresponding target type.
|
51
|
+
"""
|
52
|
+
|
53
|
+
target_type: Union[List[str], str]
|
54
|
+
current_type: Union[List[str], str]
|
55
|
+
|
56
|
+
|
57
|
+
@deprecated("This class is experimental. Use at your own risk.", category=ExperimentalClassWarning)
|
58
|
+
@dataclass
|
59
|
+
class SchemaTypeIdentifier:
|
60
|
+
"""
|
61
|
+
Identifies schema details for dynamic schema extraction and processing.
|
62
|
+
"""
|
63
|
+
|
64
|
+
key_pointer: List[Union[InterpolatedString, str]]
|
65
|
+
parameters: InitVar[Mapping[str, Any]]
|
66
|
+
type_pointer: Optional[List[Union[InterpolatedString, str]]] = None
|
67
|
+
types_mapping: Optional[List[TypesMap]] = None
|
68
|
+
schema_pointer: Optional[List[Union[InterpolatedString, str]]] = None
|
69
|
+
|
70
|
+
def __post_init__(self, parameters: Mapping[str, Any]) -> None:
|
71
|
+
self.schema_pointer = (
|
72
|
+
self._update_pointer(self.schema_pointer, parameters) if self.schema_pointer else []
|
73
|
+
) # type: ignore[assignment] # This is reqired field in model
|
74
|
+
self.key_pointer = self._update_pointer(self.key_pointer, parameters) # type: ignore[assignment] # This is reqired field in model
|
75
|
+
self.type_pointer = (
|
76
|
+
self._update_pointer(self.type_pointer, parameters) if self.type_pointer else None
|
77
|
+
)
|
78
|
+
|
79
|
+
@staticmethod
|
80
|
+
def _update_pointer(
|
81
|
+
pointer: Optional[List[Union[InterpolatedString, str]]], parameters: Mapping[str, Any]
|
82
|
+
) -> Optional[List[Union[InterpolatedString, str]]]:
|
83
|
+
return (
|
84
|
+
[
|
85
|
+
InterpolatedString.create(path, parameters=parameters)
|
86
|
+
if isinstance(path, str)
|
87
|
+
else path
|
88
|
+
for path in pointer
|
89
|
+
]
|
90
|
+
if pointer
|
91
|
+
else None
|
92
|
+
)
|
93
|
+
|
94
|
+
|
95
|
+
@deprecated("This class is experimental. Use at your own risk.", category=ExperimentalClassWarning)
|
96
|
+
@dataclass
|
97
|
+
class DynamicSchemaLoader(SchemaLoader):
|
98
|
+
"""
|
99
|
+
Dynamically loads a JSON Schema by extracting data from retrieved records.
|
100
|
+
"""
|
101
|
+
|
102
|
+
retriever: Retriever
|
103
|
+
config: Config
|
104
|
+
parameters: InitVar[Mapping[str, Any]]
|
105
|
+
schema_type_identifier: SchemaTypeIdentifier
|
106
|
+
|
107
|
+
def get_json_schema(self) -> Mapping[str, Any]:
|
108
|
+
"""
|
109
|
+
Constructs a JSON Schema based on retrieved data.
|
110
|
+
"""
|
111
|
+
properties = {}
|
112
|
+
retrieved_record = next(self.retriever.read_records({}), None) # type: ignore[call-overload] # read_records return Iterable data type
|
113
|
+
|
114
|
+
raw_schema = (
|
115
|
+
self._extract_data(
|
116
|
+
retrieved_record, # type: ignore[arg-type] # Expected that retrieved_record will be only Mapping[str, Any]
|
117
|
+
self.schema_type_identifier.schema_pointer,
|
118
|
+
)
|
119
|
+
if retrieved_record
|
120
|
+
else []
|
121
|
+
)
|
122
|
+
|
123
|
+
for property_definition in raw_schema:
|
124
|
+
key = self._get_key(property_definition, self.schema_type_identifier.key_pointer)
|
125
|
+
value = self._get_type(
|
126
|
+
property_definition,
|
127
|
+
self.schema_type_identifier.type_pointer,
|
128
|
+
)
|
129
|
+
properties[key] = value
|
130
|
+
|
131
|
+
return {
|
132
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
133
|
+
"type": "object",
|
134
|
+
"properties": properties,
|
135
|
+
}
|
136
|
+
|
137
|
+
def _get_key(
|
138
|
+
self,
|
139
|
+
raw_schema: MutableMapping[str, Any],
|
140
|
+
field_key_path: List[Union[InterpolatedString, str]],
|
141
|
+
) -> str:
|
142
|
+
"""
|
143
|
+
Extracts the key field from the schema using the specified path.
|
144
|
+
"""
|
145
|
+
field_key = self._extract_data(raw_schema, field_key_path)
|
146
|
+
if not isinstance(field_key, str):
|
147
|
+
raise ValueError(f"Expected key to be a string. Got {field_key}")
|
148
|
+
return field_key
|
149
|
+
|
150
|
+
def _get_type(
|
151
|
+
self,
|
152
|
+
raw_schema: MutableMapping[str, Any],
|
153
|
+
field_type_path: Optional[List[Union[InterpolatedString, str]]],
|
154
|
+
) -> Union[Mapping[str, Any], List[Mapping[str, Any]]]:
|
155
|
+
"""
|
156
|
+
Determines the JSON Schema type for a field, supporting nullable and combined types.
|
157
|
+
"""
|
158
|
+
raw_field_type = (
|
159
|
+
self._extract_data(raw_schema, field_type_path, default="string")
|
160
|
+
if field_type_path
|
161
|
+
else "string"
|
162
|
+
)
|
163
|
+
mapped_field_type = self._replace_type_if_not_valid(raw_field_type)
|
164
|
+
if (
|
165
|
+
isinstance(mapped_field_type, list)
|
166
|
+
and len(mapped_field_type) == 2
|
167
|
+
and all(isinstance(item, str) for item in mapped_field_type)
|
168
|
+
):
|
169
|
+
first_type = self._get_airbyte_type(mapped_field_type[0])
|
170
|
+
second_type = self._get_airbyte_type(mapped_field_type[1])
|
171
|
+
return {"oneOf": [first_type, second_type]}
|
172
|
+
elif isinstance(mapped_field_type, str):
|
173
|
+
return self._get_airbyte_type(mapped_field_type)
|
174
|
+
else:
|
175
|
+
raise ValueError(
|
176
|
+
f"Invalid data type. Available string or two items list of string. Got {mapped_field_type}."
|
177
|
+
)
|
178
|
+
|
179
|
+
def _replace_type_if_not_valid(
|
180
|
+
self, field_type: Union[List[str], str]
|
181
|
+
) -> Union[List[str], str]:
|
182
|
+
"""
|
183
|
+
Replaces a field type if it matches a type mapping in `types_map`.
|
184
|
+
"""
|
185
|
+
if self.schema_type_identifier.types_mapping:
|
186
|
+
for types_map in self.schema_type_identifier.types_mapping:
|
187
|
+
if field_type == types_map.current_type:
|
188
|
+
return types_map.target_type
|
189
|
+
return field_type
|
190
|
+
|
191
|
+
@staticmethod
|
192
|
+
def _get_airbyte_type(field_type: str) -> Mapping[str, Any]:
|
193
|
+
"""
|
194
|
+
Maps a field type to its corresponding Airbyte type definition.
|
195
|
+
"""
|
196
|
+
if field_type not in AIRBYTE_DATA_TYPES:
|
197
|
+
raise ValueError(f"Invalid Airbyte data type: {field_type}")
|
198
|
+
|
199
|
+
return deepcopy(AIRBYTE_DATA_TYPES[field_type])
|
200
|
+
|
201
|
+
def _extract_data(
|
202
|
+
self,
|
203
|
+
body: Mapping[str, Any],
|
204
|
+
extraction_path: Optional[List[Union[InterpolatedString, str]]] = None,
|
205
|
+
default: Any = None,
|
206
|
+
) -> Any:
|
207
|
+
"""
|
208
|
+
Extracts data from the body based on the provided extraction path.
|
209
|
+
"""
|
210
|
+
|
211
|
+
if not extraction_path:
|
212
|
+
return body
|
213
|
+
|
214
|
+
path = [
|
215
|
+
node.eval(self.config) if not isinstance(node, str) else node
|
216
|
+
for node in extraction_path
|
217
|
+
]
|
218
|
+
|
219
|
+
return dpath.get(body, path, default=default) # type: ignore # extracted will be a MutableMapping, given input data structure
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: airbyte-cdk
|
3
|
-
Version: 6.9.0
|
3
|
+
Version: 6.9.0.dev0
|
4
4
|
Summary: A framework for writing Airbyte Connectors.
|
5
5
|
Home-page: https://airbyte.com
|
6
6
|
License: MIT
|
@@ -18,10 +18,12 @@ Classifier: Programming Language :: Python :: 3.12
|
|
18
18
|
Classifier: Topic :: Scientific/Engineering
|
19
19
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
20
20
|
Provides-Extra: file-based
|
21
|
+
Provides-Extra: sphinx-docs
|
21
22
|
Provides-Extra: sql
|
22
23
|
Provides-Extra: vector-db-based
|
23
24
|
Requires-Dist: Jinja2 (>=3.1.2,<3.2.0)
|
24
25
|
Requires-Dist: PyYAML (>=6.0.1,<7.0.0)
|
26
|
+
Requires-Dist: Sphinx (>=4.2,<4.3) ; extra == "sphinx-docs"
|
25
27
|
Requires-Dist: airbyte-protocol-models-dataclasses (>=0.14,<0.15)
|
26
28
|
Requires-Dist: avro (>=1.11.2,<1.12.0) ; extra == "file-based"
|
27
29
|
Requires-Dist: backoff
|
@@ -61,6 +63,7 @@ Requires-Dist: rapidfuzz (>=3.10.1,<4.0.0)
|
|
61
63
|
Requires-Dist: requests
|
62
64
|
Requires-Dist: requests_cache
|
63
65
|
Requires-Dist: serpyco-rs (>=1.10.2,<2.0.0)
|
66
|
+
Requires-Dist: sphinx-rtd-theme (>=1.0,<1.1) ; extra == "sphinx-docs"
|
64
67
|
Requires-Dist: sqlalchemy (>=2.0,<3.0,!=2.0.36) ; extra == "sql"
|
65
68
|
Requires-Dist: tiktoken (==0.8.0) ; extra == "vector-db-based"
|
66
69
|
Requires-Dist: unstructured.pytesseract (>=0.3.12) ; extra == "file-based"
|
@@ -62,11 +62,11 @@ airbyte_cdk/sources/declarative/checks/check_stream.py,sha256=dAA-UhmMj0WLXCkRQr
|
|
62
62
|
airbyte_cdk/sources/declarative/checks/connection_checker.py,sha256=MBRJo6WJlZQHpIfOGaNOkkHUmgUl_4wDM6VPo41z5Ss,1383
|
63
63
|
airbyte_cdk/sources/declarative/concurrency_level/__init__.py,sha256=5XUqrmlstYlMM0j6crktlKQwALek0uiz2D3WdM46MyA,191
|
64
64
|
airbyte_cdk/sources/declarative/concurrency_level/concurrency_level.py,sha256=YIwCTCpOr_QSNW4ltQK0yUGWInI8PKNY216HOOegYLk,2101
|
65
|
-
airbyte_cdk/sources/declarative/concurrent_declarative_source.py,sha256=
|
65
|
+
airbyte_cdk/sources/declarative/concurrent_declarative_source.py,sha256=hgKamhOh1B8RA4Fx8FmCl4ORc7eO2h_RhxbkQovh3FM,23724
|
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=ZCYl6v0miacvpIt6M8FakkGZpEsY8SmB4_436sHEw9Y,126841
|
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,12 +104,12 @@ 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=qjzXe162aUcaq1n6B8KhA6Z9B8boM9yY8dAsLXll5-g,89872
|
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
|
-
airbyte_cdk/sources/declarative/parsers/manifest_component_transformer.py,sha256=
|
110
|
+
airbyte_cdk/sources/declarative/parsers/manifest_component_transformer.py,sha256=KflzFl_ZKRSW9XkH16sfr5-9HnAAI0T5s8CVBrJK2Ao,8958
|
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=
|
112
|
+
airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py,sha256=kGU0re3R-Ujtn6Gp96KpEVRHJB5P-B8sRa0aMR_jDdk,102536
|
113
113
|
airbyte_cdk/sources/declarative/partition_routers/__init__.py,sha256=1NjaZoGAIefvWwj6wx-LOKIXXWS-UnBlZFnuR7y6uYA,745
|
114
114
|
airbyte_cdk/sources/declarative/partition_routers/cartesian_product_stream_slicer.py,sha256=c5cuVFM6NFkuQqG8Z5IwkBuwDrvXZN1CunUOM_L0ezg,6892
|
115
115
|
airbyte_cdk/sources/declarative/partition_routers/list_partition_router.py,sha256=t7pRdFWfFWJtQQG19c9PVeMODyO2BknRTakpM5U9N-8,4844
|
@@ -159,8 +159,9 @@ airbyte_cdk/sources/declarative/retrievers/__init__.py,sha256=FVQpUGVwp2Gibk4gp0
|
|
159
159
|
airbyte_cdk/sources/declarative/retrievers/async_retriever.py,sha256=WDFnjrXLz3-YEjFhmlMkWAn9AJvnZ0mk9FyC8DAhEYk,4976
|
160
160
|
airbyte_cdk/sources/declarative/retrievers/retriever.py,sha256=XPLs593Xv8c5cKMc37XzUAYmzlXd1a7eSsspM-CMuWA,1696
|
161
161
|
airbyte_cdk/sources/declarative/retrievers/simple_retriever.py,sha256=N4swGw5mfuTXJ2R7AKX18CHzizsr69pXwt5uSHLPi48,24172
|
162
|
-
airbyte_cdk/sources/declarative/schema/__init__.py,sha256=
|
162
|
+
airbyte_cdk/sources/declarative/schema/__init__.py,sha256=Io9vninzlEjQ2uFmWklxfwNM0cXfljtzOz5zL1OVyT4,701
|
163
163
|
airbyte_cdk/sources/declarative/schema/default_schema_loader.py,sha256=KTACrIE23a83wsm3Rd9Eb4K6-20lrGqYxTHNp9yxsso,1820
|
164
|
+
airbyte_cdk/sources/declarative/schema/dynamic_schema_loader.py,sha256=tP5DIEMn-k2JshWeXmo53ZEudDAVb4AJ50Z5tfme_ZU,8063
|
164
165
|
airbyte_cdk/sources/declarative/schema/inline_schema_loader.py,sha256=bVETE10hRsatRJq3R3BeyRR0wIoK3gcP1gcpVRQ_P5U,464
|
165
166
|
airbyte_cdk/sources/declarative/schema/json_file_schema_loader.py,sha256=5Wl-fqW-pVf_dxJ4yGHMAFfC4JjKHYJhqFJT1xA57F4,4177
|
166
167
|
airbyte_cdk/sources/declarative/schema/schema_loader.py,sha256=kjt8v0N5wWKA5zyLnrDLxf1PJKdUqvQq2RVnAOAzNSY,379
|
@@ -333,8 +334,8 @@ airbyte_cdk/utils/slice_hasher.py,sha256=-pHexlNYoWYPnXNH-M7HEbjmeJe9Zk7SJijdQ7d
|
|
333
334
|
airbyte_cdk/utils/spec_schema_transformations.py,sha256=-5HTuNsnDBAhj-oLeQXwpTGA0HdcjFOf2zTEMUTTg_Y,816
|
334
335
|
airbyte_cdk/utils/stream_status_utils.py,sha256=ZmBoiy5HVbUEHAMrUONxZvxnvfV9CesmQJLDTAIWnWw,1171
|
335
336
|
airbyte_cdk/utils/traced_exception.py,sha256=C8uIBuCL_E4WnBAOPSxBicD06JAldoN9fGsQDp463OY,6292
|
336
|
-
airbyte_cdk-6.9.0.dist-info/LICENSE.txt,sha256=Wfe61S4BaGPj404v8lrAbvhjYR68SHlkzeYrg3_bbuM,1051
|
337
|
-
airbyte_cdk-6.9.0.dist-info/METADATA,sha256=
|
338
|
-
airbyte_cdk-6.9.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
339
|
-
airbyte_cdk-6.9.0.dist-info/entry_points.txt,sha256=fj-e3PAQvsxsQzyyq8UkG1k8spunWnD4BAH2AwlR6NM,95
|
340
|
-
airbyte_cdk-6.9.0.dist-info/RECORD,,
|
337
|
+
airbyte_cdk-6.9.0.dev0.dist-info/LICENSE.txt,sha256=Wfe61S4BaGPj404v8lrAbvhjYR68SHlkzeYrg3_bbuM,1051
|
338
|
+
airbyte_cdk-6.9.0.dev0.dist-info/METADATA,sha256=VS_vbZgaobGxk6eCGkFZuQgCR-xzMrHzJWL2FpCnyM8,6112
|
339
|
+
airbyte_cdk-6.9.0.dev0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
340
|
+
airbyte_cdk-6.9.0.dev0.dist-info/entry_points.txt,sha256=fj-e3PAQvsxsQzyyq8UkG1k8spunWnD4BAH2AwlR6NM,95
|
341
|
+
airbyte_cdk-6.9.0.dev0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|