airbyte-cdk 6.43.0.dev0__py3-none-any.whl → 6.44.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.
Files changed (23) hide show
  1. airbyte_cdk/connector_builder/connector_builder_handler.py +22 -8
  2. airbyte_cdk/connector_builder/main.py +3 -3
  3. airbyte_cdk/sources/declarative/checks/__init__.py +5 -2
  4. airbyte_cdk/sources/declarative/checks/check_stream.py +113 -11
  5. airbyte_cdk/sources/declarative/declarative_component_schema.yaml +23 -129
  6. airbyte_cdk/sources/declarative/manifest_declarative_source.py +6 -0
  7. airbyte_cdk/sources/declarative/models/declarative_component_schema.py +21 -87
  8. airbyte_cdk/sources/declarative/parsers/manifest_component_transformer.py +16 -4
  9. airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py +44 -192
  10. airbyte_cdk/sources/declarative/requesters/request_options/interpolated_request_options_provider.py +2 -25
  11. airbyte_cdk/sources/declarative/retrievers/simple_retriever.py +31 -100
  12. airbyte_cdk/sources/declarative/transformations/add_fields.py +3 -1
  13. {airbyte_cdk-6.43.0.dev0.dist-info → airbyte_cdk-6.44.0.dist-info}/METADATA +1 -1
  14. {airbyte_cdk-6.43.0.dev0.dist-info → airbyte_cdk-6.44.0.dist-info}/RECORD +18 -23
  15. airbyte_cdk/sources/declarative/requesters/query_properties/__init__.py +0 -14
  16. airbyte_cdk/sources/declarative/requesters/query_properties/group_by_key.py +0 -24
  17. airbyte_cdk/sources/declarative/requesters/query_properties/properties_from_endpoint.py +0 -40
  18. airbyte_cdk/sources/declarative/requesters/query_properties/property_chunking.py +0 -65
  19. airbyte_cdk/sources/declarative/requesters/query_properties/query_properties.py +0 -48
  20. {airbyte_cdk-6.43.0.dev0.dist-info → airbyte_cdk-6.44.0.dist-info}/LICENSE.txt +0 -0
  21. {airbyte_cdk-6.43.0.dev0.dist-info → airbyte_cdk-6.44.0.dist-info}/LICENSE_SHORT +0 -0
  22. {airbyte_cdk-6.43.0.dev0.dist-info → airbyte_cdk-6.44.0.dist-info}/WHEEL +0 -0
  23. {airbyte_cdk-6.43.0.dev0.dist-info → airbyte_cdk-6.44.0.dist-info}/entry_points.txt +0 -0
@@ -4,7 +4,7 @@
4
4
 
5
5
  import copy
6
6
  import typing
7
- from typing import Any, Mapping
7
+ from typing import Any, Mapping, Optional
8
8
 
9
9
  PARAMETERS_STR = "$parameters"
10
10
 
@@ -94,6 +94,7 @@ class ManifestComponentTransformer:
94
94
  parent_field_identifier: str,
95
95
  declarative_component: Mapping[str, Any],
96
96
  parent_parameters: Mapping[str, Any],
97
+ use_parent_parameters: Optional[bool] = None,
97
98
  ) -> Mapping[str, Any]:
98
99
  """
99
100
  Recursively transforms the specified declarative component and subcomponents to propagate parameters and insert the
@@ -103,6 +104,7 @@ class ManifestComponentTransformer:
103
104
  :param declarative_component: The current component that is having type and parameters added
104
105
  :param parent_field_identifier: The name of the field of the current component coming from the parent component
105
106
  :param parent_parameters: The parameters set on parent components defined before the current component
107
+ :param use_parent_parameters: If set, parent parameters will be used as the source of truth when key names are the same
106
108
  :return: A deep copy of the transformed component with types and parameters persisted to it
107
109
  """
108
110
  propagated_component = dict(copy.deepcopy(declarative_component))
@@ -130,7 +132,11 @@ class ManifestComponentTransformer:
130
132
  # level take precedence
131
133
  current_parameters = dict(copy.deepcopy(parent_parameters))
132
134
  component_parameters = propagated_component.pop(PARAMETERS_STR, {})
133
- current_parameters = {**current_parameters, **component_parameters}
135
+ current_parameters = (
136
+ {**component_parameters, **current_parameters}
137
+ if use_parent_parameters
138
+ else {**current_parameters, **component_parameters}
139
+ )
134
140
 
135
141
  # Parameters should be applied to the current component fields with the existing field taking precedence over parameters if
136
142
  # both exist
@@ -145,7 +151,10 @@ class ManifestComponentTransformer:
145
151
  excluded_parameter = current_parameters.pop(field_name, None)
146
152
  parent_type_field_identifier = f"{propagated_component.get('type')}.{field_name}"
147
153
  propagated_component[field_name] = self.propagate_types_and_parameters(
148
- parent_type_field_identifier, field_value, current_parameters
154
+ parent_type_field_identifier,
155
+ field_value,
156
+ current_parameters,
157
+ use_parent_parameters=use_parent_parameters,
149
158
  )
150
159
  if excluded_parameter:
151
160
  current_parameters[field_name] = excluded_parameter
@@ -158,7 +167,10 @@ class ManifestComponentTransformer:
158
167
  f"{propagated_component.get('type')}.{field_name}"
159
168
  )
160
169
  field_value[i] = self.propagate_types_and_parameters(
161
- parent_type_field_identifier, element, current_parameters
170
+ parent_type_field_identifier,
171
+ element,
172
+ current_parameters,
173
+ use_parent_parameters=use_parent_parameters,
162
174
  )
163
175
  if excluded_parameter:
164
176
  current_parameters[field_name] = excluded_parameter
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c) 2025 Airbyte, Inc., all rights reserved.
2
+ # Copyright (c) 2023 Airbyte, Inc., all rights reserved.
3
3
  #
4
4
 
5
5
  from __future__ import annotations
@@ -54,7 +54,11 @@ from airbyte_cdk.sources.declarative.auth.token_provider import (
54
54
  SessionTokenProvider,
55
55
  TokenProvider,
56
56
  )
57
- from airbyte_cdk.sources.declarative.checks import CheckDynamicStream, CheckStream
57
+ from airbyte_cdk.sources.declarative.checks import (
58
+ CheckDynamicStream,
59
+ CheckStream,
60
+ DynamicStreamCheckConfig,
61
+ )
58
62
  from airbyte_cdk.sources.declarative.concurrency_level import ConcurrencyLevel
59
63
  from airbyte_cdk.sources.declarative.datetime.min_max_datetime import MinMaxDatetime
60
64
  from airbyte_cdk.sources.declarative.declarative_stream import DeclarativeStream
@@ -218,6 +222,9 @@ from airbyte_cdk.sources.declarative.models.declarative_component_schema import
218
222
  from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
219
223
  DynamicSchemaLoader as DynamicSchemaLoaderModel,
220
224
  )
225
+ from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
226
+ DynamicStreamCheckConfig as DynamicStreamCheckConfigModel,
227
+ )
221
228
  from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
222
229
  ExponentialBackoffStrategy as ExponentialBackoffStrategyModel,
223
230
  )
@@ -227,9 +234,6 @@ from airbyte_cdk.sources.declarative.models.declarative_component_schema import
227
234
  from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
228
235
  FlattenFields as FlattenFieldsModel,
229
236
  )
230
- from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
231
- GroupByKeyMergeStrategy as GroupByKeyMergeStrategyModel,
232
- )
233
237
  from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
234
238
  GroupingPartitionRouter as GroupingPartitionRouterModel,
235
239
  )
@@ -320,18 +324,6 @@ from airbyte_cdk.sources.declarative.models.declarative_component_schema import
320
324
  from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
321
325
  ParentStreamConfig as ParentStreamConfigModel,
322
326
  )
323
- from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
324
- PropertiesFromEndpoint as PropertiesFromEndpointModel,
325
- )
326
- from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
327
- PropertyChunking as PropertyChunkingModel,
328
- )
329
- from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
330
- PropertyLimitType as PropertyLimitTypeModel,
331
- )
332
- from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
333
- QueryProperties as QueryPropertiesModel,
334
- )
335
327
  from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
336
328
  Rate as RateModel,
337
329
  )
@@ -440,15 +432,6 @@ from airbyte_cdk.sources.declarative.requesters.paginators.strategies import (
440
432
  PageIncrement,
441
433
  StopConditionPaginationStrategyDecorator,
442
434
  )
443
- from airbyte_cdk.sources.declarative.requesters.query_properties import (
444
- GroupByKey,
445
- PropertiesFromEndpoint,
446
- PropertyChunking,
447
- QueryProperties,
448
- )
449
- from airbyte_cdk.sources.declarative.requesters.query_properties.property_chunking import (
450
- PropertyLimitType,
451
- )
452
435
  from airbyte_cdk.sources.declarative.requesters.request_option import RequestOptionType
453
436
  from airbyte_cdk.sources.declarative.requesters.request_options import (
454
437
  DatetimeBasedRequestOptionsProvider,
@@ -583,6 +566,7 @@ class ModelToComponentFactory:
583
566
  BasicHttpAuthenticatorModel: self.create_basic_http_authenticator,
584
567
  BearerAuthenticatorModel: self.create_bearer_authenticator,
585
568
  CheckStreamModel: self.create_check_stream,
569
+ DynamicStreamCheckConfigModel: self.create_dynamic_stream_check_config,
586
570
  CheckDynamicStreamModel: self.create_check_dynamic_stream,
587
571
  CompositeErrorHandlerModel: self.create_composite_error_handler,
588
572
  ConcurrencyLevelModel: self.create_concurrency_level,
@@ -612,7 +596,6 @@ class ModelToComponentFactory:
612
596
  ResponseToFileExtractorModel: self.create_response_to_file_extractor,
613
597
  ExponentialBackoffStrategyModel: self.create_exponential_backoff_strategy,
614
598
  SessionTokenAuthenticatorModel: self.create_session_token_authenticator,
615
- GroupByKeyMergeStrategyModel: self.create_group_by_key,
616
599
  HttpRequesterModel: self.create_http_requester,
617
600
  HttpResponseFilterModel: self.create_http_response_filter,
618
601
  InlineSchemaLoaderModel: self.create_inline_schema_loader,
@@ -642,9 +625,6 @@ class ModelToComponentFactory:
642
625
  OffsetIncrementModel: self.create_offset_increment,
643
626
  PageIncrementModel: self.create_page_increment,
644
627
  ParentStreamConfigModel: self.create_parent_stream_config,
645
- PropertiesFromEndpointModel: self.create_properties_from_endpoint,
646
- PropertyChunkingModel: self.create_property_chunking,
647
- QueryPropertiesModel: self.create_query_properties,
648
628
  RecordFilterModel: self.create_record_filter,
649
629
  RecordSelectorModel: self.create_record_selector,
650
630
  RemoveFieldsModel: self.create_remove_fields,
@@ -964,8 +944,36 @@ class ModelToComponentFactory:
964
944
  )
965
945
 
966
946
  @staticmethod
967
- def create_check_stream(model: CheckStreamModel, config: Config, **kwargs: Any) -> CheckStream:
968
- return CheckStream(stream_names=model.stream_names, parameters={})
947
+ def create_dynamic_stream_check_config(
948
+ model: DynamicStreamCheckConfigModel, config: Config, **kwargs: Any
949
+ ) -> DynamicStreamCheckConfig:
950
+ return DynamicStreamCheckConfig(
951
+ dynamic_stream_name=model.dynamic_stream_name,
952
+ stream_count=model.stream_count or 0,
953
+ )
954
+
955
+ def create_check_stream(
956
+ self, model: CheckStreamModel, config: Config, **kwargs: Any
957
+ ) -> CheckStream:
958
+ if model.dynamic_streams_check_configs is None and model.stream_names is None:
959
+ raise ValueError(
960
+ "Expected either stream_names or dynamic_streams_check_configs to be set for CheckStream"
961
+ )
962
+
963
+ dynamic_streams_check_configs = (
964
+ [
965
+ self._create_component_from_model(model=dynamic_stream_check_config, config=config)
966
+ for dynamic_stream_check_config in model.dynamic_streams_check_configs
967
+ ]
968
+ if model.dynamic_streams_check_configs
969
+ else []
970
+ )
971
+
972
+ return CheckStream(
973
+ stream_names=model.stream_names or [],
974
+ dynamic_streams_check_configs=dynamic_streams_check_configs,
975
+ parameters={},
976
+ )
969
977
 
970
978
  @staticmethod
971
979
  def create_check_dynamic_stream(
@@ -2075,8 +2083,8 @@ class ModelToComponentFactory:
2075
2083
  parameters=model.parameters or {},
2076
2084
  )
2077
2085
 
2078
- @staticmethod
2079
2086
  def create_response_to_file_extractor(
2087
+ self,
2080
2088
  model: ResponseToFileExtractorModel,
2081
2089
  **kwargs: Any,
2082
2090
  ) -> ResponseToFileExtractor:
@@ -2090,16 +2098,11 @@ class ModelToComponentFactory:
2090
2098
  factor=model.factor or 5, parameters=model.parameters or {}, config=config
2091
2099
  )
2092
2100
 
2093
- @staticmethod
2094
- def create_group_by_key(model: GroupByKeyMergeStrategyModel, config: Config) -> GroupByKey:
2095
- return GroupByKey(model.key, config=config, parameters=model.parameters or {})
2096
-
2097
2101
  def create_http_requester(
2098
2102
  self,
2099
2103
  model: HttpRequesterModel,
2100
2104
  config: Config,
2101
2105
  decoder: Decoder = JsonDecoder(parameters={}),
2102
- query_properties_key: Optional[str] = None,
2103
2106
  *,
2104
2107
  name: str,
2105
2108
  ) -> HttpRequester:
@@ -2132,7 +2135,6 @@ class ModelToComponentFactory:
2132
2135
  request_body_json=model.request_body_json,
2133
2136
  request_headers=model.request_headers,
2134
2137
  request_parameters=model.request_parameters,
2135
- query_properties_key=query_properties_key,
2136
2138
  config=config,
2137
2139
  parameters=model.parameters or {},
2138
2140
  )
@@ -2600,79 +2602,6 @@ class ModelToComponentFactory:
2600
2602
  lazy_read_pointer=model_lazy_read_pointer,
2601
2603
  )
2602
2604
 
2603
- def create_properties_from_endpoint(
2604
- self, model: PropertiesFromEndpointModel, config: Config, **kwargs: Any
2605
- ) -> PropertiesFromEndpoint:
2606
- name = "property_retriever"
2607
- retriever = self._create_component_from_model(
2608
- model=model.retriever,
2609
- config=config,
2610
- name=name,
2611
- primary_key=None,
2612
- stream_slicer=None,
2613
- transformations=[],
2614
- )
2615
- return PropertiesFromEndpoint(
2616
- property_field_path=model.property_field_path,
2617
- retriever=retriever,
2618
- config=config,
2619
- parameters=model.parameters or {},
2620
- )
2621
-
2622
- def create_property_chunking(
2623
- self, model: PropertyChunkingModel, config: Config, **kwargs: Any
2624
- ) -> PropertyChunking:
2625
- record_merge_strategy = (
2626
- self._create_component_from_model(
2627
- model=model.record_merge_strategy, config=config, **kwargs
2628
- )
2629
- if model.record_merge_strategy
2630
- else None
2631
- )
2632
-
2633
- property_limit_type: PropertyLimitType
2634
- match model.property_limit_type:
2635
- case PropertyLimitTypeModel.property_count:
2636
- property_limit_type = PropertyLimitType.property_count
2637
- case PropertyLimitTypeModel.characters:
2638
- property_limit_type = PropertyLimitType.characters
2639
- case _:
2640
- raise ValueError(f"Invalid PropertyLimitType {property_limit_type}")
2641
-
2642
- return PropertyChunking(
2643
- property_limit_type=property_limit_type,
2644
- property_limit=model.property_limit,
2645
- record_merge_strategy=record_merge_strategy,
2646
- config=config,
2647
- parameters=model.parameters or {},
2648
- )
2649
-
2650
- def create_query_properties(
2651
- self, model: QueryPropertiesModel, config: Config, **kwargs: Any
2652
- ) -> QueryProperties:
2653
- if isinstance(model.property_list, list):
2654
- property_list = model.property_list
2655
- else:
2656
- property_list = self._create_component_from_model(
2657
- model=model.property_list, config=config, **kwargs
2658
- )
2659
-
2660
- property_chunking = (
2661
- self._create_component_from_model(
2662
- model=model.property_chunking, config=config, **kwargs
2663
- )
2664
- if model.property_chunking
2665
- else None
2666
- )
2667
-
2668
- return QueryProperties(
2669
- property_list=property_list,
2670
- always_include_properties=model.always_include_properties,
2671
- property_chunking=property_chunking,
2672
- config=config,
2673
- parameters=model.parameters or {},
2674
- )
2675
-
2676
2605
  @staticmethod
2677
2606
  def create_record_filter(
2678
2607
  model: RecordFilterModel, config: Config, **kwargs: Any
@@ -2825,6 +2754,9 @@ class ModelToComponentFactory:
2825
2754
  if model.decoder
2826
2755
  else JsonDecoder(parameters={})
2827
2756
  )
2757
+ requester = self._create_component_from_model(
2758
+ model=model.requester, decoder=decoder, config=config, name=name
2759
+ )
2828
2760
  record_selector = self._create_component_from_model(
2829
2761
  model=model.record_selector,
2830
2762
  name=name,
@@ -2833,53 +2765,6 @@ class ModelToComponentFactory:
2833
2765
  transformations=transformations,
2834
2766
  client_side_incremental_sync=client_side_incremental_sync,
2835
2767
  )
2836
-
2837
- query_properties: Optional[QueryProperties] = None
2838
- query_properties_key: Optional[str] = None
2839
- if (
2840
- hasattr(model.requester, "request_parameters")
2841
- and model.requester.request_parameters
2842
- and isinstance(model.requester.request_parameters, Mapping)
2843
- ):
2844
- query_properties_definitions = []
2845
- for key, request_parameter in model.requester.request_parameters.items():
2846
- if (
2847
- isinstance(request_parameter, Mapping)
2848
- and request_parameter.get("type") == "QueryProperties"
2849
- ):
2850
- query_properties_key = key
2851
- query_properties_definitions.append(request_parameter)
2852
- elif not isinstance(request_parameter, str):
2853
- raise ValueError(
2854
- f"Each element of request_parameters should be of type str or QueryProperties, but received {request_parameter.get('type')}"
2855
- )
2856
-
2857
- if len(query_properties_definitions) > 1:
2858
- raise ValueError(
2859
- f"request_parameters should only define one QueryProperties field, but found {len(query_properties_definitions)}"
2860
- )
2861
-
2862
- if len(query_properties_definitions) == 1:
2863
- query_properties = self.create_component(
2864
- model_type=QueryPropertiesModel,
2865
- component_definition=query_properties_definitions[0],
2866
- config=config,
2867
- )
2868
-
2869
- # Removes QueryProperties components from the interpolated mappings because it will be resolved in
2870
- # the provider from the slice directly instead of through jinja interpolation
2871
- if isinstance(model.requester.request_parameters, Mapping):
2872
- model.requester.request_parameters = self._remove_query_properties(
2873
- model.requester.request_parameters
2874
- )
2875
-
2876
- requester = self._create_component_from_model(
2877
- model=model.requester,
2878
- decoder=decoder,
2879
- query_properties_key=query_properties_key,
2880
- config=config,
2881
- name=name,
2882
- )
2883
2768
  url_base = (
2884
2769
  model.requester.url_base
2885
2770
  if hasattr(model.requester, "url_base")
@@ -2985,42 +2870,9 @@ class ModelToComponentFactory:
2985
2870
  cursor=cursor,
2986
2871
  config=config,
2987
2872
  ignore_stream_slicer_parameters_on_paginated_requests=ignore_stream_slicer_parameters_on_paginated_requests,
2988
- additional_query_properties=query_properties,
2989
2873
  parameters=model.parameters or {},
2990
2874
  )
2991
2875
 
2992
- @staticmethod
2993
- def _remove_query_properties(
2994
- request_parameters: Mapping[str, Union[Any, str]],
2995
- ) -> Mapping[str, Union[Any, str]]:
2996
- return {
2997
- parameter_field: request_parameter
2998
- for parameter_field, request_parameter in request_parameters.items()
2999
- if not isinstance(request_parameter, Mapping)
3000
- or not request_parameter.get("type") == "QueryProperties"
3001
- }
3002
-
3003
- @staticmethod
3004
- def _translate_query_properties_to_interpolated_strings(
3005
- request_parameters: Mapping[str, Union[Any, str]],
3006
- ) -> Mapping[str, Union[Any, str]]:
3007
- # todo blai: remove this since unused
3008
- new_request_parameters = dict()
3009
- for key, request_parameter in request_parameters.items():
3010
- if (
3011
- isinstance(request_parameter, Mapping)
3012
- and request_parameter.get("type") == "QueryProperties"
3013
- ):
3014
- # This may seem like this could be combined into the above conditional, but this is separated
3015
- # so that we do not add the properties into the new request_parameters mapping
3016
- if request_parameter.get("inject_into"):
3017
- new_request_parameters[key] = (
3018
- "{{ stream_partition.extra_fields['query_properties'] }}"
3019
- )
3020
- else:
3021
- new_request_parameters[key] = request_parameter
3022
- return new_request_parameters
3023
-
3024
2876
  def create_state_delegating_stream(
3025
2877
  self,
3026
2878
  model: StateDelegatingStreamModel,
@@ -1,9 +1,9 @@
1
1
  #
2
- # Copyright (c) 2025 Airbyte, Inc., all rights reserved.
2
+ # Copyright (c) 2023 Airbyte, Inc., all rights reserved.
3
3
  #
4
4
 
5
5
  from dataclasses import InitVar, dataclass, field
6
- from typing import Any, List, Mapping, MutableMapping, Optional, Union
6
+ from typing import Any, Mapping, MutableMapping, Optional, Union
7
7
 
8
8
  from airbyte_cdk.sources.declarative.interpolation.interpolated_nested_mapping import NestedMapping
9
9
  from airbyte_cdk.sources.declarative.requesters.request_options.interpolated_nested_request_input_provider import (
@@ -40,7 +40,6 @@ class InterpolatedRequestOptionsProvider(RequestOptionsProvider):
40
40
  request_headers: Optional[RequestInput] = None
41
41
  request_body_data: Optional[RequestInput] = None
42
42
  request_body_json: Optional[NestedMapping] = None
43
- query_properties_key: Optional[str] = None
44
43
 
45
44
  def __post_init__(self, parameters: Mapping[str, Any]) -> None:
46
45
  if self.request_parameters is None:
@@ -84,28 +83,6 @@ class InterpolatedRequestOptionsProvider(RequestOptionsProvider):
84
83
  valid_value_types=ValidRequestTypes,
85
84
  )
86
85
  if isinstance(interpolated_value, dict):
87
- if self.query_properties_key:
88
- if not stream_slice:
89
- raise ValueError(
90
- "stream_slice should not be None if query properties in requests is enabled. Please contact Airbyte Support"
91
- )
92
- elif (
93
- "query_properties" not in stream_slice.extra_fields
94
- or stream_slice.extra_fields.get("query_properties") is None
95
- ):
96
- raise ValueError(
97
- "QueryProperties component is defined but stream_partition does not contain query_properties. Please contact Airbyte Support"
98
- )
99
- elif not isinstance(stream_slice.extra_fields.get("query_properties"), List):
100
- raise ValueError(
101
- "QueryProperties component is defined but stream_slice.extra_fields.query_properties is not a List. Please contact Airbyte Support"
102
- )
103
- interpolated_value = {
104
- **interpolated_value,
105
- self.query_properties_key: ",".join(
106
- stream_slice.extra_fields.get("query_properties") # type: ignore # Earlier type checks validate query_properties type
107
- ),
108
- }
109
86
  return interpolated_value
110
87
  return {}
111
88
 
@@ -1,9 +1,8 @@
1
1
  #
2
- # Copyright (c) 2025 Airbyte, Inc., all rights reserved.
2
+ # Copyright (c) 2023 Airbyte, Inc., all rights reserved.
3
3
  #
4
4
 
5
5
  import json
6
- from collections import defaultdict
7
6
  from dataclasses import InitVar, dataclass, field
8
7
  from functools import partial
9
8
  from itertools import islice
@@ -13,7 +12,6 @@ from typing import (
13
12
  Iterable,
14
13
  List,
15
14
  Mapping,
16
- MutableMapping,
17
15
  Optional,
18
16
  Set,
19
17
  Tuple,
@@ -33,7 +31,6 @@ from airbyte_cdk.sources.declarative.partition_routers.single_partition_router i
33
31
  )
34
32
  from airbyte_cdk.sources.declarative.requesters.paginators.no_pagination import NoPagination
35
33
  from airbyte_cdk.sources.declarative.requesters.paginators.paginator import Paginator
36
- from airbyte_cdk.sources.declarative.requesters.query_properties import QueryProperties
37
34
  from airbyte_cdk.sources.declarative.requesters.request_options import (
38
35
  DefaultRequestOptionsProvider,
39
36
  RequestOptionsProvider,
@@ -91,7 +88,6 @@ class SimpleRetriever(Retriever):
91
88
  )
92
89
  cursor: Optional[DeclarativeCursor] = None
93
90
  ignore_stream_slicer_parameters_on_paginated_requests: bool = False
94
- additional_query_properties: Optional[QueryProperties] = None
95
91
 
96
92
  def __post_init__(self, parameters: Mapping[str, Any]) -> None:
97
93
  self._paginator = self.paginator or NoPagination(parameters=parameters)
@@ -449,108 +445,43 @@ class SimpleRetriever(Retriever):
449
445
  :param stream_slice: The stream slice to read data for
450
446
  :return: The records read from the API source
451
447
  """
452
-
453
- if self.additional_query_properties:
454
- property_chunks = list(
455
- self.additional_query_properties.get_request_property_chunks(
456
- stream_slice=stream_slice
457
- )
458
- )
459
- has_multiple_chunks = self.additional_query_properties.has_multiple_chunks(
460
- stream_slice=stream_slice
461
- )
462
- else:
463
- property_chunks = [[""]]
464
- has_multiple_chunks = False
465
- merged_records: MutableMapping[str, Any] = defaultdict(dict)
466
448
  _slice = stream_slice or StreamSlice(partition={}, cursor_slice={}) # None-check
449
+
467
450
  most_recent_record_from_slice = None
451
+ record_generator = partial(
452
+ self._parse_records,
453
+ stream_slice=stream_slice,
454
+ stream_state=self.state or {},
455
+ records_schema=records_schema,
456
+ )
468
457
 
469
- if self.additional_query_properties:
470
- for properties in property_chunks:
471
- _slice = StreamSlice(
472
- partition=_slice.partition or {},
473
- cursor_slice=_slice.cursor_slice or {},
474
- extra_fields={"query_properties": properties},
475
- ) # None-check
476
-
477
- record_generator = partial(
478
- self._parse_records,
479
- stream_slice=_slice,
480
- stream_state=self.state or {},
481
- records_schema=records_schema,
482
- )
458
+ if self.cursor and isinstance(self.cursor, ResumableFullRefreshCursor):
459
+ stream_state = self.state
483
460
 
484
- for stream_data in self._read_pages(record_generator, self.state, _slice):
485
- current_record = self._extract_record(stream_data, _slice)
486
- if self.cursor and current_record:
487
- self.cursor.observe(_slice, current_record)
488
-
489
- # Latest record read, not necessarily within slice boundaries.
490
- # TODO Remove once all custom components implement `observe` method.
491
- # https://github.com/airbytehq/airbyte-internal-issues/issues/6955
492
- most_recent_record_from_slice = self._get_most_recent_record(
493
- most_recent_record_from_slice, current_record, _slice
494
- )
495
-
496
- # Record merging should only be done if there are multiple property chunks. Otherwise,
497
- # yielding immediately is more efficient so records can be emitted immediately
498
- if (
499
- has_multiple_chunks
500
- and self.additional_query_properties.property_chunking
501
- and current_record
502
- ):
503
- merge_key = (
504
- self.additional_query_properties.property_chunking.get_merge_key(
505
- current_record
506
- )
507
- )
508
- merged_records[merge_key].update(current_record)
509
- else:
510
- yield stream_data
511
- if self.cursor:
512
- self.cursor.close_slice(_slice, most_recent_record_from_slice)
461
+ # Before syncing the RFR stream, we check if the job's prior attempt was successful and don't need to
462
+ # fetch more records. The platform deletes stream state for full refresh streams before starting a
463
+ # new job, so we don't need to worry about this value existing for the initial attempt
464
+ if stream_state.get(FULL_REFRESH_SYNC_COMPLETE_KEY):
465
+ return
513
466
 
514
- if has_multiple_chunks:
515
- yield from merged_records.values()
467
+ yield from self._read_single_page(record_generator, stream_state, _slice)
516
468
  else:
517
- _slice = stream_slice or StreamSlice(partition={}, cursor_slice={}) # None-check
518
-
519
- most_recent_record_from_slice = None
520
- record_generator = partial(
521
- self._parse_records,
522
- stream_slice=stream_slice,
523
- stream_state=self.state or {},
524
- records_schema=records_schema,
525
- )
526
-
527
- if self.cursor and isinstance(self.cursor, ResumableFullRefreshCursor):
528
- stream_state = self.state
529
-
530
- # Before syncing the RFR stream, we check if the job's prior attempt was successful and don't need to
531
- # fetch more records. The platform deletes stream state for full refresh streams before starting a
532
- # new job, so we don't need to worry about this value existing for the initial attempt
533
- if stream_state.get(FULL_REFRESH_SYNC_COMPLETE_KEY):
534
- return
469
+ for stream_data in self._read_pages(record_generator, self.state, _slice):
470
+ current_record = self._extract_record(stream_data, _slice)
471
+ if self.cursor and current_record:
472
+ self.cursor.observe(_slice, current_record)
473
+
474
+ # Latest record read, not necessarily within slice boundaries.
475
+ # TODO Remove once all custom components implement `observe` method.
476
+ # https://github.com/airbytehq/airbyte-internal-issues/issues/6955
477
+ most_recent_record_from_slice = self._get_most_recent_record(
478
+ most_recent_record_from_slice, current_record, _slice
479
+ )
480
+ yield stream_data
535
481
 
536
- yield from self._read_single_page(record_generator, stream_state, _slice)
537
- else:
538
- for stream_data in self._read_pages(record_generator, self.state, _slice):
539
- current_record = self._extract_record(stream_data, _slice)
540
- if self.cursor and current_record:
541
- self.cursor.observe(_slice, current_record)
542
-
543
- # Latest record read, not necessarily within slice boundaries.
544
- # TODO Remove once all custom components implement `observe` method.
545
- # https://github.com/airbytehq/airbyte-internal-issues/issues/6955
546
- most_recent_record_from_slice = self._get_most_recent_record(
547
- most_recent_record_from_slice, current_record, _slice
548
- )
549
- yield stream_data
550
-
551
- if self.cursor:
552
- self.cursor.close_slice(_slice, most_recent_record_from_slice)
553
- return
482
+ if self.cursor:
483
+ self.cursor.close_slice(_slice, most_recent_record_from_slice)
484
+ return
554
485
 
555
486
  def _get_most_recent_record(
556
487
  self,
@@ -139,7 +139,9 @@ class AddFields(RecordTransformation):
139
139
  valid_types = (parsed_field.value_type,) if parsed_field.value_type else None
140
140
  value = parsed_field.value.eval(config, valid_types=valid_types, **kwargs)
141
141
  is_empty_condition = not self.condition
142
- if is_empty_condition or self._filter_interpolator.eval(config, value=value, **kwargs):
142
+ if is_empty_condition or self._filter_interpolator.eval(
143
+ config, value=value, path=parsed_field.path, **kwargs
144
+ ):
143
145
  dpath.new(record, parsed_field.path, value)
144
146
 
145
147
  def __eq__(self, other: Any) -> bool:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: airbyte-cdk
3
- Version: 6.43.0.dev0
3
+ Version: 6.44.0
4
4
  Summary: A framework for writing Airbyte Connectors.
5
5
  Home-page: https://airbyte.com
6
6
  License: MIT