airbyte-cdk 6.8.1rc10__py3-none-any.whl → 6.8.2.dev1__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.
Files changed (22) hide show
  1. airbyte_cdk/sources/declarative/concurrent_declarative_source.py +87 -25
  2. airbyte_cdk/sources/declarative/declarative_component_schema.yaml +2 -100
  3. airbyte_cdk/sources/declarative/extractors/record_filter.py +3 -5
  4. airbyte_cdk/sources/declarative/incremental/__init__.py +3 -0
  5. airbyte_cdk/sources/declarative/incremental/concurrent_partition_cursor.py +270 -0
  6. airbyte_cdk/sources/declarative/incremental/per_partition_cursor.py +9 -0
  7. airbyte_cdk/sources/declarative/manifest_declarative_source.py +2 -53
  8. airbyte_cdk/sources/declarative/models/declarative_component_schema.py +2 -95
  9. airbyte_cdk/sources/declarative/parsers/manifest_component_transformer.py +0 -6
  10. airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py +87 -106
  11. airbyte_cdk/sources/declarative/partition_routers/__init__.py +1 -2
  12. airbyte_cdk/sources/declarative/retrievers/simple_retriever.py +1 -1
  13. airbyte_cdk/sources/declarative/stream_slicers/declarative_partition_generator.py +0 -1
  14. airbyte_cdk/sources/streams/concurrent/cursor.py +9 -0
  15. {airbyte_cdk-6.8.1rc10.dist-info → airbyte_cdk-6.8.2.dev1.dist-info}/METADATA +1 -1
  16. {airbyte_cdk-6.8.1rc10.dist-info → airbyte_cdk-6.8.2.dev1.dist-info}/RECORD +19 -21
  17. airbyte_cdk/sources/declarative/resolvers/__init__.py +0 -13
  18. airbyte_cdk/sources/declarative/resolvers/components_resolver.py +0 -55
  19. airbyte_cdk/sources/declarative/resolvers/http_components_resolver.py +0 -106
  20. {airbyte_cdk-6.8.1rc10.dist-info → airbyte_cdk-6.8.2.dev1.dist-info}/LICENSE.txt +0 -0
  21. {airbyte_cdk-6.8.1rc10.dist-info → airbyte_cdk-6.8.2.dev1.dist-info}/WHEEL +0 -0
  22. {airbyte_cdk-6.8.1rc10.dist-info → airbyte_cdk-6.8.2.dev1.dist-info}/entry_points.txt +0 -0
@@ -39,7 +39,6 @@ from airbyte_cdk.sources.declarative.parsers.manifest_reference_resolver import
39
39
  from airbyte_cdk.sources.declarative.parsers.model_to_component_factory import (
40
40
  ModelToComponentFactory,
41
41
  )
42
- from airbyte_cdk.sources.declarative.resolvers import COMPONENTS_RESOLVER_TYPE_MAPPING
43
42
  from airbyte_cdk.sources.message import MessageRepository
44
43
  from airbyte_cdk.sources.streams.core import Stream
45
44
  from airbyte_cdk.sources.types import ConnectionDefinition
@@ -121,10 +120,7 @@ class ManifestDeclarativeSource(DeclarativeSource):
121
120
  self._emit_manifest_debug_message(
122
121
  extra_args={"source_name": self.name, "parsed_config": json.dumps(self._source_config)}
123
122
  )
124
-
125
- stream_configs = self._stream_configs(self._source_config) + self._dynamic_stream_configs(
126
- self._source_config, config
127
- )
123
+ stream_configs = self._stream_configs(self._source_config)
128
124
 
129
125
  source_streams = [
130
126
  self._constructor.create_component(
@@ -238,8 +234,7 @@ class ManifestDeclarativeSource(DeclarativeSource):
238
234
  )
239
235
 
240
236
  streams = self._source_config.get("streams")
241
- dynamic_streams = self._source_config.get("dynamic_streams")
242
- if not (streams or dynamic_streams):
237
+ if not streams:
243
238
  raise ValidationError(
244
239
  f"A valid manifest should have at least one stream defined. Got {streams}"
245
240
  )
@@ -308,51 +303,5 @@ class ManifestDeclarativeSource(DeclarativeSource):
308
303
  s["type"] = "DeclarativeStream"
309
304
  return stream_configs
310
305
 
311
- def _dynamic_stream_configs(
312
- self, manifest: Mapping[str, Any], config: Mapping[str, Any]
313
- ) -> List[Dict[str, Any]]:
314
- dynamic_stream_definitions: List[Dict[str, Any]] = manifest.get("dynamic_streams", [])
315
- dynamic_stream_configs: List[Dict[str, Any]] = []
316
-
317
- for dynamic_definition in dynamic_stream_definitions:
318
- components_resolver_config = dynamic_definition["components_resolver"]
319
-
320
- if not components_resolver_config:
321
- raise ValueError(
322
- f"Missing 'components_resolver' in dynamic definition: {dynamic_definition}"
323
- )
324
-
325
- resolver_type = components_resolver_config.get("type")
326
- if not resolver_type:
327
- raise ValueError(
328
- f"Missing 'type' in components resolver configuration: {components_resolver_config}"
329
- )
330
-
331
- if resolver_type not in COMPONENTS_RESOLVER_TYPE_MAPPING:
332
- raise ValueError(
333
- f"Invalid components resolver type '{resolver_type}'. "
334
- f"Expected one of {list(COMPONENTS_RESOLVER_TYPE_MAPPING.keys())}."
335
- )
336
-
337
- if "retriever" in components_resolver_config:
338
- components_resolver_config["retriever"]["requester"]["use_cache"] = True
339
-
340
- # Create a resolver for dynamic components based on type
341
- components_resolver = self._constructor.create_component(
342
- COMPONENTS_RESOLVER_TYPE_MAPPING[resolver_type], components_resolver_config, config
343
- )
344
-
345
- stream_template_config = dynamic_definition["stream_template"]
346
-
347
- for dynamic_stream in components_resolver.resolve_components(
348
- stream_template_config=stream_template_config
349
- ):
350
- if "type" not in dynamic_stream:
351
- dynamic_stream["type"] = "DeclarativeStream"
352
-
353
- dynamic_stream_configs.append(dynamic_stream)
354
-
355
- return dynamic_stream_configs
356
-
357
306
  def _emit_manifest_debug_message(self, extra_args: dict[str, Any]) -> None:
358
307
  self.logger.debug("declarative source created from manifest", extra=extra_args)
@@ -1158,37 +1158,6 @@ class WaitUntilTimeFromHeader(BaseModel):
1158
1158
  parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
1159
1159
 
1160
1160
 
1161
- class ComponentMappingDefinition(BaseModel):
1162
- type: Literal["ComponentMappingDefinition"]
1163
- field_path: List[str] = Field(
1164
- ...,
1165
- description="A list of potentially nested fields indicating the full path where value will be added or updated.",
1166
- examples=[
1167
- ["data"],
1168
- ["data", "records"],
1169
- ["data", "{{ parameters.name }}"],
1170
- ["data", "*", "record"],
1171
- ],
1172
- title="Field Path",
1173
- )
1174
- value: str = Field(
1175
- ...,
1176
- description="The dynamic or static value to assign to the key. Interpolated values can be used to dynamically determine the value during runtime.",
1177
- examples=[
1178
- "{{ components_values['updates'] }}",
1179
- "{{ components_values['MetaData']['LastUpdatedTime'] }}",
1180
- "{{ config['segment_id'] }}",
1181
- ],
1182
- title="Value",
1183
- )
1184
- value_type: Optional[ValueType] = Field(
1185
- None,
1186
- description="The expected data type of the value. If omitted, the type will be inferred from the value provided.",
1187
- title="Value Type",
1188
- )
1189
- parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
1190
-
1191
-
1192
1161
  class AddedFieldDefinition(BaseModel):
1193
1162
  type: Literal["AddedFieldDefinition"]
1194
1163
  path: List[str] = Field(
@@ -1486,40 +1455,13 @@ class CompositeErrorHandler(BaseModel):
1486
1455
  parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
1487
1456
 
1488
1457
 
1489
- class DeclarativeSource1(BaseModel):
1458
+ class DeclarativeSource(BaseModel):
1490
1459
  class Config:
1491
1460
  extra = Extra.forbid
1492
1461
 
1493
1462
  type: Literal["DeclarativeSource"]
1494
1463
  check: CheckStream
1495
1464
  streams: List[DeclarativeStream]
1496
- dynamic_streams: Optional[List[DynamicDeclarativeStream]] = None
1497
- version: str = Field(
1498
- ...,
1499
- description="The version of the Airbyte CDK used to build and test the source.",
1500
- )
1501
- schemas: Optional[Schemas] = None
1502
- definitions: Optional[Dict[str, Any]] = None
1503
- spec: Optional[Spec] = None
1504
- concurrency_level: Optional[ConcurrencyLevel] = None
1505
- metadata: Optional[Dict[str, Any]] = Field(
1506
- None,
1507
- description="For internal Airbyte use only - DO NOT modify manually. Used by consumers of declarative manifests for storing related metadata.",
1508
- )
1509
- description: Optional[str] = Field(
1510
- None,
1511
- description="A description of the connector. It will be presented on the Source documentation page.",
1512
- )
1513
-
1514
-
1515
- class DeclarativeSource2(BaseModel):
1516
- class Config:
1517
- extra = Extra.forbid
1518
-
1519
- type: Literal["DeclarativeSource"]
1520
- check: CheckStream
1521
- streams: Optional[List[DeclarativeStream]] = None
1522
- dynamic_streams: List[DynamicDeclarativeStream]
1523
1465
  version: str = Field(
1524
1466
  ...,
1525
1467
  description="The version of the Airbyte CDK used to build and test the source.",
@@ -1538,17 +1480,6 @@ class DeclarativeSource2(BaseModel):
1538
1480
  )
1539
1481
 
1540
1482
 
1541
- class DeclarativeSource(BaseModel):
1542
- class Config:
1543
- extra = Extra.forbid
1544
-
1545
- __root__: Union[DeclarativeSource1, DeclarativeSource2] = Field(
1546
- ...,
1547
- description="An API source that extracts data according to its declarative components.",
1548
- title="DeclarativeSource",
1549
- )
1550
-
1551
-
1552
1483
  class SelectiveAuthenticator(BaseModel):
1553
1484
  class Config:
1554
1485
  extra = Extra.allow
@@ -1952,32 +1883,8 @@ class SubstreamPartitionRouter(BaseModel):
1952
1883
  parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
1953
1884
 
1954
1885
 
1955
- class HttpComponentsResolver(BaseModel):
1956
- type: Literal["HttpComponentsResolver"]
1957
- retriever: Union[AsyncRetriever, CustomRetriever, SimpleRetriever] = Field(
1958
- ...,
1959
- description="Component used to coordinate how records are extracted across stream slices and request pages.",
1960
- title="Retriever",
1961
- )
1962
- components_mapping: List[ComponentMappingDefinition]
1963
- parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
1964
-
1965
-
1966
- class DynamicDeclarativeStream(BaseModel):
1967
- type: Literal["DynamicDeclarativeStream"]
1968
- stream_template: DeclarativeStream = Field(
1969
- ..., description="Reference to the stream template.", title="Stream Template"
1970
- )
1971
- components_resolver: HttpComponentsResolver = Field(
1972
- ...,
1973
- description="Component resolve and populates stream templates with components values.",
1974
- title="Components Resolver",
1975
- )
1976
-
1977
-
1978
1886
  CompositeErrorHandler.update_forward_refs()
1979
- DeclarativeSource1.update_forward_refs()
1980
- DeclarativeSource2.update_forward_refs()
1887
+ DeclarativeSource.update_forward_refs()
1981
1888
  SelectiveAuthenticator.update_forward_refs()
1982
1889
  DeclarativeStream.update_forward_refs()
1983
1890
  SessionTokenAuthenticator.update_forward_refs()
@@ -31,12 +31,6 @@ DEFAULT_MODEL_TYPES: Mapping[str, str] = {
31
31
  # DeclarativeStream
32
32
  "DeclarativeStream.retriever": "SimpleRetriever",
33
33
  "DeclarativeStream.schema_loader": "JsonFileSchemaLoader",
34
- # DynamicDeclarativeStream
35
- "DynamicDeclarativeStream.stream_template": "DeclarativeStream",
36
- "DynamicDeclarativeStream.components_resolver": "HttpComponentsResolver",
37
- # HttpComponentsResolver
38
- "HttpComponentsResolver.retriever": "SimpleRetriever",
39
- "HttpComponentsResolver.components_mapping": "ComponentMappingDefinition",
40
34
  # DefaultErrorHandler
41
35
  "DefaultErrorHandler.response_filters": "HttpResponseFilter",
42
36
  # DefaultPaginator
@@ -81,6 +81,8 @@ from airbyte_cdk.sources.declarative.extractors.record_selector import (
81
81
  )
82
82
  from airbyte_cdk.sources.declarative.incremental import (
83
83
  ChildPartitionResumableFullRefreshCursor,
84
+ ConcurrentCursorFactory,
85
+ ConcurrentPerPartitionCursor,
84
86
  CursorFactory,
85
87
  DatetimeBasedCursor,
86
88
  DeclarativeCursor,
@@ -119,9 +121,6 @@ from airbyte_cdk.sources.declarative.models.declarative_component_schema import
119
121
  from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
120
122
  CheckStream as CheckStreamModel,
121
123
  )
122
- from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
123
- ComponentMappingDefinition as ComponentMappingDefinitionModel,
124
- )
125
124
  from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
126
125
  CompositeErrorHandler as CompositeErrorHandlerModel,
127
126
  )
@@ -194,9 +193,6 @@ from airbyte_cdk.sources.declarative.models.declarative_component_schema import
194
193
  from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
195
194
  GzipJsonDecoder as GzipJsonDecoderModel,
196
195
  )
197
- from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
198
- HttpComponentsResolver as HttpComponentsResolverModel,
199
- )
200
196
  from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
201
197
  HttpRequester as HttpRequesterModel,
202
198
  )
@@ -304,7 +300,6 @@ from airbyte_cdk.sources.declarative.models.declarative_component_schema import
304
300
  from airbyte_cdk.sources.declarative.partition_routers import (
305
301
  CartesianProductStreamSlicer,
306
302
  ListPartitionRouter,
307
- PartitionRouter,
308
303
  SinglePartitionRouter,
309
304
  SubstreamPartitionRouter,
310
305
  )
@@ -345,10 +340,6 @@ from airbyte_cdk.sources.declarative.requesters.request_options import (
345
340
  )
346
341
  from airbyte_cdk.sources.declarative.requesters.request_path import RequestPath
347
342
  from airbyte_cdk.sources.declarative.requesters.requester import HttpMethod
348
- from airbyte_cdk.sources.declarative.resolvers import (
349
- ComponentMappingDefinition,
350
- HttpComponentsResolver,
351
- )
352
343
  from airbyte_cdk.sources.declarative.retrievers import (
353
344
  AsyncRetriever,
354
345
  SimpleRetriever,
@@ -478,8 +469,6 @@ class ModelToComponentFactory:
478
469
  WaitTimeFromHeaderModel: self.create_wait_time_from_header,
479
470
  WaitUntilTimeFromHeaderModel: self.create_wait_until_time_from_header,
480
471
  AsyncRetrieverModel: self.create_async_retriever,
481
- HttpComponentsResolverModel: self.create_http_components_resolver,
482
- ComponentMappingDefinitionModel: self.create_components_mapping_definition,
483
472
  }
484
473
 
485
474
  # Needed for the case where we need to perform a second parse on the fields of a custom component
@@ -918,6 +907,62 @@ class ModelToComponentFactory:
918
907
  cursor_granularity=cursor_granularity,
919
908
  )
920
909
 
910
+ def create_concurrent_cursor_from_perpartition_cursor(
911
+ self,
912
+ state_manager: ConnectorStateManager,
913
+ model_type: Type[BaseModel],
914
+ component_definition: ComponentDefinition,
915
+ stream_name: str,
916
+ stream_namespace: Optional[str],
917
+ config: Config,
918
+ stream_state: MutableMapping[str, Any],
919
+ partition_router,
920
+ **kwargs: Any,
921
+ ) -> ConcurrentPerPartitionCursor:
922
+ component_type = component_definition.get("type")
923
+ if component_definition.get("type") != model_type.__name__:
924
+ raise ValueError(
925
+ f"Expected manifest component of type {model_type.__name__}, but received {component_type} instead"
926
+ )
927
+
928
+ datetime_based_cursor_model = model_type.parse_obj(component_definition)
929
+
930
+ if not isinstance(datetime_based_cursor_model, DatetimeBasedCursorModel):
931
+ raise ValueError(
932
+ f"Expected {model_type.__name__} component, but received {datetime_based_cursor_model.__class__.__name__}"
933
+ )
934
+
935
+ interpolated_cursor_field = InterpolatedString.create(
936
+ datetime_based_cursor_model.cursor_field,
937
+ parameters=datetime_based_cursor_model.parameters or {},
938
+ )
939
+ cursor_field = CursorField(interpolated_cursor_field.eval(config=config))
940
+
941
+ # Create the cursor factory
942
+ cursor_factory = ConcurrentCursorFactory(
943
+ partial(
944
+ self.create_concurrent_cursor_from_datetime_based_cursor,
945
+ state_manager=state_manager,
946
+ model_type=model_type,
947
+ component_definition=component_definition,
948
+ stream_name=stream_name,
949
+ stream_namespace=stream_namespace,
950
+ config=config,
951
+ )
952
+ )
953
+
954
+ # Return the concurrent cursor and state converter
955
+ return ConcurrentPerPartitionCursor(
956
+ cursor_factory=cursor_factory,
957
+ partition_router=partition_router,
958
+ stream_name=stream_name,
959
+ stream_namespace=stream_namespace,
960
+ stream_state=stream_state,
961
+ message_repository=self._message_repository, # type: ignore
962
+ connector_state_manager=state_manager,
963
+ cursor_field=cursor_field,
964
+ )
965
+
921
966
  @staticmethod
922
967
  def create_constant_backoff_strategy(
923
968
  model: ConstantBackoffStrategyModel, config: Config, **kwargs: Any
@@ -1200,17 +1245,14 @@ class ModelToComponentFactory:
1200
1245
  raise ValueError(
1201
1246
  "Unsupported Slicer is used. PerPartitionWithGlobalCursor should be used here instead"
1202
1247
  )
1248
+ cursor = combined_slicers if isinstance(
1249
+ combined_slicers, (PerPartitionWithGlobalCursor, GlobalSubstreamCursor)
1250
+ ) else self._create_component_from_model(
1251
+ model=model.incremental_sync, config=config
1252
+ )
1253
+
1203
1254
  client_side_incremental_sync = {
1204
- "date_time_based_cursor": self._create_component_from_model(
1205
- model=model.incremental_sync, config=config
1206
- ),
1207
- "substream_cursor": (
1208
- combined_slicers
1209
- if isinstance(
1210
- combined_slicers, (PerPartitionWithGlobalCursor, GlobalSubstreamCursor)
1211
- )
1212
- else None
1213
- ),
1255
+ "cursor": cursor
1214
1256
  }
1215
1257
 
1216
1258
  if model.incremental_sync and isinstance(model.incremental_sync, DatetimeBasedCursorModel):
@@ -1294,20 +1336,19 @@ class ModelToComponentFactory:
1294
1336
  parameters=model.parameters or {},
1295
1337
  )
1296
1338
 
1297
- def _build_stream_slicer_from_partition_router(
1298
- self,
1299
- model: Union[AsyncRetrieverModel, CustomRetrieverModel, SimpleRetrieverModel],
1300
- config: Config,
1301
- ) -> Optional[PartitionRouter]:
1339
+ def _merge_stream_slicers(
1340
+ self, model: DeclarativeStreamModel, config: Config
1341
+ ) -> Optional[StreamSlicer]:
1342
+ stream_slicer = None
1302
1343
  if (
1303
- hasattr(model, "partition_router")
1304
- and isinstance(model, SimpleRetrieverModel)
1305
- and model.partition_router
1344
+ hasattr(model.retriever, "partition_router")
1345
+ and isinstance(model.retriever, SimpleRetrieverModel)
1346
+ and model.retriever.partition_router
1306
1347
  ):
1307
- stream_slicer_model = model.partition_router
1348
+ stream_slicer_model = model.retriever.partition_router
1308
1349
 
1309
1350
  if isinstance(stream_slicer_model, list):
1310
- return CartesianProductStreamSlicer(
1351
+ stream_slicer = CartesianProductStreamSlicer(
1311
1352
  [
1312
1353
  self._create_component_from_model(model=slicer, config=config)
1313
1354
  for slicer in stream_slicer_model
@@ -1315,24 +1356,9 @@ class ModelToComponentFactory:
1315
1356
  parameters={},
1316
1357
  )
1317
1358
  else:
1318
- return self._create_component_from_model(model=stream_slicer_model, config=config) # type: ignore[no-any-return]
1319
- # Will be created PartitionRouter as stream_slicer_model is model.partition_router
1320
- return None
1321
-
1322
- def _build_resumable_cursor_from_paginator(
1323
- self,
1324
- model: Union[AsyncRetrieverModel, CustomRetrieverModel, SimpleRetrieverModel],
1325
- stream_slicer: Optional[StreamSlicer],
1326
- ) -> Optional[StreamSlicer]:
1327
- if hasattr(model, "paginator") and model.paginator and not stream_slicer:
1328
- # For the regular Full-Refresh streams, we use the high level `ResumableFullRefreshCursor`
1329
- return ResumableFullRefreshCursor(parameters={})
1330
- return None
1331
-
1332
- def _merge_stream_slicers(
1333
- self, model: DeclarativeStreamModel, config: Config
1334
- ) -> Optional[StreamSlicer]:
1335
- stream_slicer = self._build_stream_slicer_from_partition_router(model.retriever, config)
1359
+ stream_slicer = self._create_component_from_model(
1360
+ model=stream_slicer_model, config=config
1361
+ )
1336
1362
 
1337
1363
  if model.incremental_sync and stream_slicer:
1338
1364
  incremental_sync_model = model.incremental_sync
@@ -1375,7 +1401,15 @@ class ModelToComponentFactory:
1375
1401
  ),
1376
1402
  partition_router=stream_slicer,
1377
1403
  )
1378
- return self._build_resumable_cursor_from_paginator(model.retriever, stream_slicer)
1404
+ elif (
1405
+ hasattr(model.retriever, "paginator")
1406
+ and model.retriever.paginator
1407
+ and not stream_slicer
1408
+ ):
1409
+ # For the regular Full-Refresh streams, we use the high level `ResumableFullRefreshCursor`
1410
+ return ResumableFullRefreshCursor(parameters={})
1411
+ else:
1412
+ return None
1379
1413
 
1380
1414
  def create_default_error_handler(
1381
1415
  self, model: DefaultErrorHandlerModel, config: Config, **kwargs: Any
@@ -1932,7 +1966,7 @@ class ModelToComponentFactory:
1932
1966
  if (
1933
1967
  not isinstance(stream_slicer, DatetimeBasedCursor)
1934
1968
  or type(stream_slicer) is not DatetimeBasedCursor
1935
- ):
1969
+ ) and not isinstance(stream_slicer, PerPartitionWithGlobalCursor):
1936
1970
  # Many of the custom component implementations of DatetimeBasedCursor override get_request_params() (or other methods).
1937
1971
  # Because we're decoupling RequestOptionsProvider from the Cursor, custom components will eventually need to reimplement
1938
1972
  # their own RequestOptionsProvider. However, right now the existing StreamSlicer/Cursor still can act as the SimpleRetriever's
@@ -2239,56 +2273,3 @@ class ModelToComponentFactory:
2239
2273
 
2240
2274
  def _evaluate_log_level(self, emit_connector_builder_messages: bool) -> Level:
2241
2275
  return Level.DEBUG if emit_connector_builder_messages else Level.INFO
2242
-
2243
- @staticmethod
2244
- def create_components_mapping_definition(
2245
- model: ComponentMappingDefinitionModel, config: Config, **kwargs: Any
2246
- ) -> ComponentMappingDefinition:
2247
- interpolated_value = InterpolatedString.create(
2248
- model.value, parameters=model.parameters or {}
2249
- )
2250
- field_path = [
2251
- InterpolatedString.create(path, parameters=model.parameters or {})
2252
- for path in model.field_path
2253
- ]
2254
- return ComponentMappingDefinition(
2255
- field_path=field_path, # type: ignore[arg-type] # field_path can be str and InterpolatedString
2256
- value=interpolated_value,
2257
- value_type=ModelToComponentFactory._json_schema_type_name_to_type(model.value_type),
2258
- parameters=model.parameters or {},
2259
- )
2260
-
2261
- def create_http_components_resolver(
2262
- self, model: HttpComponentsResolverModel, config: Config
2263
- ) -> Any:
2264
- stream_slicer = self._build_stream_slicer_from_partition_router(model.retriever, config)
2265
- combined_slicers = self._build_resumable_cursor_from_paginator(
2266
- model.retriever, stream_slicer
2267
- )
2268
-
2269
- retriever = self._create_component_from_model(
2270
- model=model.retriever,
2271
- config=config,
2272
- name="",
2273
- primary_key=None,
2274
- stream_slicer=combined_slicers,
2275
- transformations=[],
2276
- )
2277
-
2278
- components_mapping = [
2279
- self._create_component_from_model(
2280
- model=components_mapping_definition_model,
2281
- value_type=ModelToComponentFactory._json_schema_type_name_to_type(
2282
- components_mapping_definition_model.value_type
2283
- ),
2284
- config=config,
2285
- )
2286
- for components_mapping_definition_model in model.components_mapping
2287
- ]
2288
-
2289
- return HttpComponentsResolver(
2290
- retriever=retriever,
2291
- config=config,
2292
- components_mapping=components_mapping,
2293
- parameters=model.parameters or {},
2294
- )
@@ -6,6 +6,5 @@ from airbyte_cdk.sources.declarative.partition_routers.cartesian_product_stream_
6
6
  from airbyte_cdk.sources.declarative.partition_routers.list_partition_router import ListPartitionRouter
7
7
  from airbyte_cdk.sources.declarative.partition_routers.single_partition_router import SinglePartitionRouter
8
8
  from airbyte_cdk.sources.declarative.partition_routers.substream_partition_router import SubstreamPartitionRouter
9
- from airbyte_cdk.sources.declarative.partition_routers.partition_router import PartitionRouter
10
9
 
11
- __all__ = ["CartesianProductStreamSlicer", "ListPartitionRouter", "SinglePartitionRouter", "SubstreamPartitionRouter", "PartitionRouter"]
10
+ __all__ = ["CartesianProductStreamSlicer", "ListPartitionRouter", "SinglePartitionRouter", "SubstreamPartitionRouter"]
@@ -178,7 +178,7 @@ class SimpleRetriever(Retriever):
178
178
  stream_slice,
179
179
  next_page_token,
180
180
  self._paginator.get_request_headers,
181
- self.stream_slicer.get_request_headers,
181
+ self.request_option_provider.get_request_headers,
182
182
  )
183
183
  if isinstance(headers, str):
184
184
  raise ValueError("Request headers cannot be a string")
@@ -38,7 +38,6 @@ class DeclarativePartitionFactory:
38
38
  stream_slice,
39
39
  )
40
40
 
41
-
42
41
  class DeclarativePartition(Partition):
43
42
  def __init__(
44
43
  self,
@@ -240,6 +240,15 @@ class ConcurrentCursor(Cursor):
240
240
  def _extract_cursor_value(self, record: Record) -> Any:
241
241
  return self._connector_state_converter.parse_value(self._cursor_field.extract_value(record))
242
242
 
243
+ def close_partition_without_emit(self, partition: Partition) -> None:
244
+ slice_count_before = len(self.state.get("slices", []))
245
+ self._add_slice_to_state(partition)
246
+ if slice_count_before < len(
247
+ self.state["slices"]
248
+ ): # only emit if at least one slice has been processed
249
+ self._merge_partitions()
250
+ self._has_closed_at_least_one_slice = True
251
+
243
252
  def close_partition(self, partition: Partition) -> None:
244
253
  slice_count_before = len(self.state.get("slices", []))
245
254
  self._add_slice_to_state(partition)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: airbyte-cdk
3
- Version: 6.8.1rc10
3
+ Version: 6.8.2.dev1
4
4
  Summary: A framework for writing Airbyte Connectors.
5
5
  Home-page: https://airbyte.com
6
6
  License: MIT