airbyte-cdk 6.43.0.dev0__py3-none-any.whl → 6.43.1__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 (21) 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/declarative_component_schema.yaml +1 -128
  4. airbyte_cdk/sources/declarative/manifest_declarative_source.py +6 -0
  5. airbyte_cdk/sources/declarative/models/declarative_component_schema.py +1 -80
  6. airbyte_cdk/sources/declarative/parsers/manifest_component_transformer.py +16 -4
  7. airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py +5 -189
  8. airbyte_cdk/sources/declarative/requesters/request_options/interpolated_request_options_provider.py +2 -25
  9. airbyte_cdk/sources/declarative/retrievers/simple_retriever.py +31 -100
  10. airbyte_cdk/sources/declarative/transformations/add_fields.py +3 -1
  11. {airbyte_cdk-6.43.0.dev0.dist-info → airbyte_cdk-6.43.1.dist-info}/METADATA +1 -1
  12. {airbyte_cdk-6.43.0.dev0.dist-info → airbyte_cdk-6.43.1.dist-info}/RECORD +16 -21
  13. airbyte_cdk/sources/declarative/requesters/query_properties/__init__.py +0 -14
  14. airbyte_cdk/sources/declarative/requesters/query_properties/group_by_key.py +0 -24
  15. airbyte_cdk/sources/declarative/requesters/query_properties/properties_from_endpoint.py +0 -40
  16. airbyte_cdk/sources/declarative/requesters/query_properties/property_chunking.py +0 -65
  17. airbyte_cdk/sources/declarative/requesters/query_properties/query_properties.py +0 -48
  18. {airbyte_cdk-6.43.0.dev0.dist-info → airbyte_cdk-6.43.1.dist-info}/LICENSE.txt +0 -0
  19. {airbyte_cdk-6.43.0.dev0.dist-info → airbyte_cdk-6.43.1.dist-info}/LICENSE_SHORT +0 -0
  20. {airbyte_cdk-6.43.0.dev0.dist-info → airbyte_cdk-6.43.1.dist-info}/WHEEL +0 -0
  21. {airbyte_cdk-6.43.0.dev0.dist-info → airbyte_cdk-6.43.1.dist-info}/entry_points.txt +0 -0
@@ -4,7 +4,7 @@
4
4
 
5
5
 
6
6
  from dataclasses import asdict, dataclass, field
7
- from typing import Any, List, Mapping
7
+ from typing import Any, Dict, List, Mapping
8
8
 
9
9
  from airbyte_cdk.connector_builder.test_reader import TestReader
10
10
  from airbyte_cdk.models import (
@@ -27,30 +27,34 @@ from airbyte_cdk.utils.traced_exception import AirbyteTracedException
27
27
  DEFAULT_MAXIMUM_NUMBER_OF_PAGES_PER_SLICE = 5
28
28
  DEFAULT_MAXIMUM_NUMBER_OF_SLICES = 5
29
29
  DEFAULT_MAXIMUM_RECORDS = 100
30
+ DEFAULT_MAXIMUM_STREAMS = 100
30
31
 
31
32
  MAX_PAGES_PER_SLICE_KEY = "max_pages_per_slice"
32
33
  MAX_SLICES_KEY = "max_slices"
33
34
  MAX_RECORDS_KEY = "max_records"
35
+ MAX_STREAMS_KEY = "max_streams"
34
36
 
35
37
 
36
38
  @dataclass
37
- class TestReadLimits:
39
+ class TestLimits:
38
40
  max_records: int = field(default=DEFAULT_MAXIMUM_RECORDS)
39
41
  max_pages_per_slice: int = field(default=DEFAULT_MAXIMUM_NUMBER_OF_PAGES_PER_SLICE)
40
42
  max_slices: int = field(default=DEFAULT_MAXIMUM_NUMBER_OF_SLICES)
43
+ max_streams: int = field(default=DEFAULT_MAXIMUM_STREAMS)
41
44
 
42
45
 
43
- def get_limits(config: Mapping[str, Any]) -> TestReadLimits:
46
+ def get_limits(config: Mapping[str, Any]) -> TestLimits:
44
47
  command_config = config.get("__test_read_config", {})
45
48
  max_pages_per_slice = (
46
49
  command_config.get(MAX_PAGES_PER_SLICE_KEY) or DEFAULT_MAXIMUM_NUMBER_OF_PAGES_PER_SLICE
47
50
  )
48
51
  max_slices = command_config.get(MAX_SLICES_KEY) or DEFAULT_MAXIMUM_NUMBER_OF_SLICES
49
52
  max_records = command_config.get(MAX_RECORDS_KEY) or DEFAULT_MAXIMUM_RECORDS
50
- return TestReadLimits(max_records, max_pages_per_slice, max_slices)
53
+ max_streams = command_config.get(MAX_STREAMS_KEY) or DEFAULT_MAXIMUM_STREAMS
54
+ return TestLimits(max_records, max_pages_per_slice, max_slices, max_streams)
51
55
 
52
56
 
53
- def create_source(config: Mapping[str, Any], limits: TestReadLimits) -> ManifestDeclarativeSource:
57
+ def create_source(config: Mapping[str, Any], limits: TestLimits) -> ManifestDeclarativeSource:
54
58
  manifest = config["__injected_declarative_manifest"]
55
59
  return ManifestDeclarativeSource(
56
60
  config=config,
@@ -71,7 +75,7 @@ def read_stream(
71
75
  config: Mapping[str, Any],
72
76
  configured_catalog: ConfiguredAirbyteCatalog,
73
77
  state: List[AirbyteStateMessage],
74
- limits: TestReadLimits,
78
+ limits: TestLimits,
75
79
  ) -> AirbyteMessage:
76
80
  try:
77
81
  test_read_handler = TestReader(
@@ -117,13 +121,23 @@ def resolve_manifest(source: ManifestDeclarativeSource) -> AirbyteMessage:
117
121
  return error.as_airbyte_message()
118
122
 
119
123
 
120
- def full_resolve_manifest(source: ManifestDeclarativeSource) -> AirbyteMessage:
124
+ def full_resolve_manifest(source: ManifestDeclarativeSource, limits: TestLimits) -> AirbyteMessage:
121
125
  try:
122
126
  manifest = {**source.resolved_manifest}
123
127
  streams = manifest.get("streams", [])
124
128
  for stream in streams:
125
129
  stream["dynamic_stream_name"] = None
126
- streams.extend(source.dynamic_streams)
130
+
131
+ mapped_streams: Dict[str, List[Dict[str, Any]]] = {}
132
+ for stream in source.dynamic_streams:
133
+ generated_streams = mapped_streams.setdefault(stream["dynamic_stream_name"], [])
134
+
135
+ if len(generated_streams) < limits.max_streams:
136
+ generated_streams += [stream]
137
+
138
+ for generated_streams_list in mapped_streams.values():
139
+ streams.extend(generated_streams_list)
140
+
127
141
  manifest["streams"] = streams
128
142
  return AirbyteMessage(
129
143
  type=Type.RECORD,
@@ -10,7 +10,7 @@ import orjson
10
10
 
11
11
  from airbyte_cdk.connector import BaseConnector
12
12
  from airbyte_cdk.connector_builder.connector_builder_handler import (
13
- TestReadLimits,
13
+ TestLimits,
14
14
  create_source,
15
15
  full_resolve_manifest,
16
16
  get_limits,
@@ -73,7 +73,7 @@ def handle_connector_builder_request(
73
73
  config: Mapping[str, Any],
74
74
  catalog: Optional[ConfiguredAirbyteCatalog],
75
75
  state: List[AirbyteStateMessage],
76
- limits: TestReadLimits,
76
+ limits: TestLimits,
77
77
  ) -> AirbyteMessage:
78
78
  if command == "resolve_manifest":
79
79
  return resolve_manifest(source)
@@ -83,7 +83,7 @@ def handle_connector_builder_request(
83
83
  ), "`test_read` requires a valid `ConfiguredAirbyteCatalog`, got None."
84
84
  return read_stream(source, config, catalog, state, limits)
85
85
  elif command == "full_resolve_manifest":
86
- return full_resolve_manifest(source)
86
+ return full_resolve_manifest(source, limits)
87
87
  else:
88
88
  raise ValueError(f"Unrecognized command {command}.")
89
89
 
@@ -1023,15 +1023,6 @@ definitions:
1023
1023
  $parameters:
1024
1024
  type: object
1025
1025
  additionalProperties: true
1026
- EmitPartialRecordMergeStrategy:
1027
- title: Emit Partial Record
1028
- description: Record merge strategy where in the case where multiple requests are needed to retrieve all properties, properties are not consolidated back into a single record and are instead emitted as separate groups of properties. This strategy should only be used when records do not have a unique identifier like a primary key.
1029
- required:
1030
- - type
1031
- properties:
1032
- type:
1033
- type: string
1034
- enum: [EmitPartialRecordMergeStrategy]
1035
1026
  JwtAuthenticator:
1036
1027
  title: JWT Authenticator
1037
1028
  description: Authenticator for requests using JWT authentication flow.
@@ -1740,30 +1731,6 @@ definitions:
1740
1731
  $parameters:
1741
1732
  type: object
1742
1733
  additionalProperties: true
1743
- GroupByKeyMergeStrategy:
1744
- title: Group by Key
1745
- description: Record merge strategy that combines records according to fields on the record.
1746
- required:
1747
- - type
1748
- - key
1749
- properties:
1750
- type:
1751
- type: string
1752
- enum: [GroupByKeyMergeStrategy]
1753
- key:
1754
- title: Key
1755
- description: The name of the field on the record whose value will be used to group properties that were retrieved through multiple API requests.
1756
- anyOf:
1757
- - type: string
1758
- - type: array
1759
- items:
1760
- type: string
1761
- examples:
1762
- - "id"
1763
- - ["parent_id", "end_date"]
1764
- $parameters:
1765
- type: object
1766
- additionalProperties: true
1767
1734
  SessionTokenAuthenticator:
1768
1735
  type: object
1769
1736
  required:
@@ -1983,9 +1950,7 @@ definitions:
1983
1950
  - type: string
1984
1951
  - type: object
1985
1952
  additionalProperties:
1986
- anyOf:
1987
- - type: string
1988
- - $ref": "#/definitions/QueryProperties"
1953
+ type: string
1989
1954
  interpolation_context:
1990
1955
  - next_page_token
1991
1956
  - stream_interval
@@ -3003,98 +2968,6 @@ definitions:
3003
2968
  examples:
3004
2969
  - id
3005
2970
  - ["code", "type"]
3006
- PropertiesFromEndpoint:
3007
- title: Properties from Endpoint
3008
- description: Defines the behavior for fetching the list of properties from an API that will be loaded into the requests to extract records.
3009
- type: object
3010
- required:
3011
- - type
3012
- - property_field_path
3013
- - retriever
3014
- properties:
3015
- type:
3016
- type: string
3017
- enum: [PropertiesFromEndpoint]
3018
- property_field_path:
3019
- description: Describes the path to the field that should be extracted
3020
- type: array
3021
- items:
3022
- type: string
3023
- examples:
3024
- - ["name"]
3025
- interpolation_context:
3026
- - config
3027
- - parameters
3028
- retriever:
3029
- description: Requester component that describes how to fetch the properties to query from a remote API endpoint.
3030
- anyOf:
3031
- - "$ref": "#/definitions/CustomRetriever"
3032
- - "$ref": "#/definitions/SimpleRetriever"
3033
- $parameters:
3034
- type: object
3035
- additionalProperties: true
3036
- PropertyChunking:
3037
- title: Property Chunking
3038
- description: For APIs with restrictions on the amount of properties that can be requester per request, property chunking can be applied to make multiple requests with a subset of the properties.
3039
- type: object
3040
- required:
3041
- - type
3042
- - property_limit_type
3043
- properties:
3044
- type:
3045
- type: string
3046
- enum: [PropertyChunking]
3047
- property_limit_type:
3048
- title: Property Limit Type
3049
- description: The type used to determine the maximum number of properties per chunk
3050
- enum:
3051
- - characters
3052
- - property_count
3053
- property_limit:
3054
- title: Property Limit
3055
- description: The maximum amount of properties that can be retrieved per request according to the limit type.
3056
- type: integer
3057
- record_merge_strategy:
3058
- title: Record Merge Strategy
3059
- description: Dictates how to records that require multiple requests to get all properties should be emitted to the destination
3060
- anyOf:
3061
- - "$ref": "#/definitions/EmitPartialRecordMergeStrategy"
3062
- - "$ref": "#/definitions/GroupByKeyMergeStrategy"
3063
- $parameters:
3064
- type: object
3065
- additionalProperties: true
3066
- QueryProperties:
3067
- title: Query Properties
3068
- description: For APIs that require explicit specification of the properties to query for, this component specifies which property fields and how they are supplied to outbound requests.
3069
- type: object
3070
- required:
3071
- - type
3072
- - property_list
3073
- properties:
3074
- type:
3075
- type: string
3076
- enum: [QueryProperties]
3077
- property_list:
3078
- title: Property List
3079
- description: The set of properties that will be queried for in the outbound request. This can either be statically defined or dynamic based on an API endpoint
3080
- anyOf:
3081
- - type: array
3082
- items:
3083
- type: string
3084
- - "$ref": "#/definitions/PropertiesFromEndpoint"
3085
- always_include_properties:
3086
- title: Always Include Properties
3087
- description: The list of properties that should be included in every set of properties when multiple chunks of properties are being requested.
3088
- type: array
3089
- items:
3090
- type: string
3091
- property_chunking:
3092
- title: Property Chunking
3093
- description: Defines how query properties will be grouped into smaller sets for APIs with limitations on the number of properties fetched per API request.
3094
- "$ref": "#/definitions/PropertyChunking"
3095
- $parameters:
3096
- type: object
3097
- additionalProperties: true
3098
2971
  RecordFilter:
3099
2972
  title: Record Filter
3100
2973
  description: Filter applied on a list of records.
@@ -397,6 +397,12 @@ class ManifestDeclarativeSource(DeclarativeSource):
397
397
  for dynamic_stream in components_resolver.resolve_components(
398
398
  stream_template_config=stream_template_config
399
399
  ):
400
+ dynamic_stream = {
401
+ **ManifestComponentTransformer().propagate_types_and_parameters(
402
+ "", dynamic_stream, {}, use_parent_parameters=True
403
+ )
404
+ }
405
+
400
406
  if "type" not in dynamic_stream:
401
407
  dynamic_stream["type"] = "DeclarativeStream"
402
408
 
@@ -1,5 +1,3 @@
1
- # Copyright (c) 2025 Airbyte, Inc., all rights reserved.
2
-
3
1
  # generated by datamodel-codegen:
4
2
  # filename: declarative_component_schema.yaml
5
3
 
@@ -345,10 +343,6 @@ class Clamping(BaseModel):
345
343
  target_details: Optional[Dict[str, Any]] = None
346
344
 
347
345
 
348
- class EmitPartialRecordMergeStrategy(BaseModel):
349
- type: Literal["EmitPartialRecordMergeStrategy"]
350
-
351
-
352
346
  class Algorithm(Enum):
353
347
  HS256 = "HS256"
354
348
  HS384 = "HS384"
@@ -722,17 +716,6 @@ class ExponentialBackoffStrategy(BaseModel):
722
716
  parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
723
717
 
724
718
 
725
- class GroupByKeyMergeStrategy(BaseModel):
726
- type: Literal["GroupByKeyMergeStrategy"]
727
- key: Union[str, List[str]] = Field(
728
- ...,
729
- description="The name of the field on the record whose value will be used to group properties that were retrieved through multiple API requests.",
730
- examples=["id", ["parent_id", "end_date"]],
731
- title="Key",
732
- )
733
- parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
734
-
735
-
736
719
  class SessionTokenRequestBearerAuthenticator(BaseModel):
737
720
  type: Literal["Bearer"]
738
721
 
@@ -1204,33 +1187,6 @@ class PrimaryKey(BaseModel):
1204
1187
  )
1205
1188
 
1206
1189
 
1207
- class PropertyLimitType(Enum):
1208
- characters = "characters"
1209
- property_count = "property_count"
1210
-
1211
-
1212
- class PropertyChunking(BaseModel):
1213
- type: Literal["PropertyChunking"]
1214
- property_limit_type: PropertyLimitType = Field(
1215
- ...,
1216
- description="The type used to determine the maximum number of properties per chunk",
1217
- title="Property Limit Type",
1218
- )
1219
- property_limit: Optional[int] = Field(
1220
- None,
1221
- description="The maximum amount of properties that can be retrieved per request according to the limit type.",
1222
- title="Property Limit",
1223
- )
1224
- record_merge_strategy: Optional[
1225
- Union[EmitPartialRecordMergeStrategy, GroupByKeyMergeStrategy]
1226
- ] = Field(
1227
- None,
1228
- description="Dictates how to records that require multiple requests to get all properties should be emitted to the destination",
1229
- title="Record Merge Strategy",
1230
- )
1231
- parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
1232
-
1233
-
1234
1190
  class RecordFilter(BaseModel):
1235
1191
  type: Literal["RecordFilter"]
1236
1192
  condition: Optional[str] = Field(
@@ -2218,7 +2174,7 @@ class HttpRequester(BaseModel):
2218
2174
  examples=[{"Output-Format": "JSON"}, {"Version": "{{ config['version'] }}"}],
2219
2175
  title="Request Headers",
2220
2176
  )
2221
- request_parameters: Optional[Union[str, Dict[str, Union[str, Any]]]] = Field(
2177
+ request_parameters: Optional[Union[str, Dict[str, str]]] = Field(
2222
2178
  None,
2223
2179
  description="Specifies the query parameters that should be set on an outgoing HTTP request given the inputs.",
2224
2180
  examples=[
@@ -2308,40 +2264,6 @@ class ParentStreamConfig(BaseModel):
2308
2264
  parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
2309
2265
 
2310
2266
 
2311
- class PropertiesFromEndpoint(BaseModel):
2312
- type: Literal["PropertiesFromEndpoint"]
2313
- property_field_path: List[str] = Field(
2314
- ...,
2315
- description="Describes the path to the field that should be extracted",
2316
- examples=[["name"]],
2317
- )
2318
- retriever: Union[CustomRetriever, SimpleRetriever] = Field(
2319
- ...,
2320
- description="Requester component that describes how to fetch the properties to query from a remote API endpoint.",
2321
- )
2322
- parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
2323
-
2324
-
2325
- class QueryProperties(BaseModel):
2326
- type: Literal["QueryProperties"]
2327
- property_list: Union[List[str], PropertiesFromEndpoint] = Field(
2328
- ...,
2329
- description="The set of properties that will be queried for in the outbound request. This can either be statically defined or dynamic based on an API endpoint",
2330
- title="Property List",
2331
- )
2332
- always_include_properties: Optional[List[str]] = Field(
2333
- None,
2334
- description="The list of properties that should be included in every set of properties when multiple chunks of properties are being requested.",
2335
- title="Always Include Properties",
2336
- )
2337
- property_chunking: Optional[PropertyChunking] = Field(
2338
- None,
2339
- description="Defines how query properties will be grouped into smaller sets for APIs with limitations on the number of properties fetched per API request.",
2340
- title="Property Chunking",
2341
- )
2342
- parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
2343
-
2344
-
2345
2267
  class StateDelegatingStream(BaseModel):
2346
2268
  type: Literal["StateDelegatingStream"]
2347
2269
  name: str = Field(..., description="The stream name.", example=["Users"], title="Name")
@@ -2590,6 +2512,5 @@ DeclarativeStream.update_forward_refs()
2590
2512
  SessionTokenAuthenticator.update_forward_refs()
2591
2513
  DynamicSchemaLoader.update_forward_refs()
2592
2514
  ParentStreamConfig.update_forward_refs()
2593
- PropertiesFromEndpoint.update_forward_refs()
2594
2515
  SimpleRetriever.update_forward_refs()
2595
2516
  AsyncRetriever.update_forward_refs()
@@ -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
@@ -227,9 +227,6 @@ from airbyte_cdk.sources.declarative.models.declarative_component_schema import
227
227
  from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
228
228
  FlattenFields as FlattenFieldsModel,
229
229
  )
230
- from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
231
- GroupByKeyMergeStrategy as GroupByKeyMergeStrategyModel,
232
- )
233
230
  from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
234
231
  GroupingPartitionRouter as GroupingPartitionRouterModel,
235
232
  )
@@ -320,18 +317,6 @@ from airbyte_cdk.sources.declarative.models.declarative_component_schema import
320
317
  from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
321
318
  ParentStreamConfig as ParentStreamConfigModel,
322
319
  )
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
320
  from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
336
321
  Rate as RateModel,
337
322
  )
@@ -440,15 +425,6 @@ from airbyte_cdk.sources.declarative.requesters.paginators.strategies import (
440
425
  PageIncrement,
441
426
  StopConditionPaginationStrategyDecorator,
442
427
  )
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
428
  from airbyte_cdk.sources.declarative.requesters.request_option import RequestOptionType
453
429
  from airbyte_cdk.sources.declarative.requesters.request_options import (
454
430
  DatetimeBasedRequestOptionsProvider,
@@ -612,7 +588,6 @@ class ModelToComponentFactory:
612
588
  ResponseToFileExtractorModel: self.create_response_to_file_extractor,
613
589
  ExponentialBackoffStrategyModel: self.create_exponential_backoff_strategy,
614
590
  SessionTokenAuthenticatorModel: self.create_session_token_authenticator,
615
- GroupByKeyMergeStrategyModel: self.create_group_by_key,
616
591
  HttpRequesterModel: self.create_http_requester,
617
592
  HttpResponseFilterModel: self.create_http_response_filter,
618
593
  InlineSchemaLoaderModel: self.create_inline_schema_loader,
@@ -642,9 +617,6 @@ class ModelToComponentFactory:
642
617
  OffsetIncrementModel: self.create_offset_increment,
643
618
  PageIncrementModel: self.create_page_increment,
644
619
  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
620
  RecordFilterModel: self.create_record_filter,
649
621
  RecordSelectorModel: self.create_record_selector,
650
622
  RemoveFieldsModel: self.create_remove_fields,
@@ -2075,8 +2047,8 @@ class ModelToComponentFactory:
2075
2047
  parameters=model.parameters or {},
2076
2048
  )
2077
2049
 
2078
- @staticmethod
2079
2050
  def create_response_to_file_extractor(
2051
+ self,
2080
2052
  model: ResponseToFileExtractorModel,
2081
2053
  **kwargs: Any,
2082
2054
  ) -> ResponseToFileExtractor:
@@ -2090,16 +2062,11 @@ class ModelToComponentFactory:
2090
2062
  factor=model.factor or 5, parameters=model.parameters or {}, config=config
2091
2063
  )
2092
2064
 
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
2065
  def create_http_requester(
2098
2066
  self,
2099
2067
  model: HttpRequesterModel,
2100
2068
  config: Config,
2101
2069
  decoder: Decoder = JsonDecoder(parameters={}),
2102
- query_properties_key: Optional[str] = None,
2103
2070
  *,
2104
2071
  name: str,
2105
2072
  ) -> HttpRequester:
@@ -2132,7 +2099,6 @@ class ModelToComponentFactory:
2132
2099
  request_body_json=model.request_body_json,
2133
2100
  request_headers=model.request_headers,
2134
2101
  request_parameters=model.request_parameters,
2135
- query_properties_key=query_properties_key,
2136
2102
  config=config,
2137
2103
  parameters=model.parameters or {},
2138
2104
  )
@@ -2600,79 +2566,6 @@ class ModelToComponentFactory:
2600
2566
  lazy_read_pointer=model_lazy_read_pointer,
2601
2567
  )
2602
2568
 
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
2569
  @staticmethod
2677
2570
  def create_record_filter(
2678
2571
  model: RecordFilterModel, config: Config, **kwargs: Any
@@ -2825,6 +2718,9 @@ class ModelToComponentFactory:
2825
2718
  if model.decoder
2826
2719
  else JsonDecoder(parameters={})
2827
2720
  )
2721
+ requester = self._create_component_from_model(
2722
+ model=model.requester, decoder=decoder, config=config, name=name
2723
+ )
2828
2724
  record_selector = self._create_component_from_model(
2829
2725
  model=model.record_selector,
2830
2726
  name=name,
@@ -2833,53 +2729,6 @@ class ModelToComponentFactory:
2833
2729
  transformations=transformations,
2834
2730
  client_side_incremental_sync=client_side_incremental_sync,
2835
2731
  )
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
2732
  url_base = (
2884
2733
  model.requester.url_base
2885
2734
  if hasattr(model.requester, "url_base")
@@ -2985,42 +2834,9 @@ class ModelToComponentFactory:
2985
2834
  cursor=cursor,
2986
2835
  config=config,
2987
2836
  ignore_stream_slicer_parameters_on_paginated_requests=ignore_stream_slicer_parameters_on_paginated_requests,
2988
- additional_query_properties=query_properties,
2989
2837
  parameters=model.parameters or {},
2990
2838
  )
2991
2839
 
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
2840
  def create_state_delegating_stream(
3025
2841
  self,
3026
2842
  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.43.1
4
4
  Summary: A framework for writing Airbyte Connectors.
5
5
  Home-page: https://airbyte.com
6
6
  License: MIT
@@ -7,8 +7,8 @@ airbyte_cdk/config_observation.py,sha256=7SSPxtN0nXPkm4euGNcTTr1iLbwUL01jy-24V1H
7
7
  airbyte_cdk/connector.py,sha256=bO23kdGRkl8XKFytOgrrWFc_VagteTHVEF6IsbizVkM,4224
8
8
  airbyte_cdk/connector_builder/README.md,sha256=Hw3wvVewuHG9-QgsAq1jDiKuLlStDxKBz52ftyNRnBw,1665
9
9
  airbyte_cdk/connector_builder/__init__.py,sha256=4Hw-PX1-VgESLF16cDdvuYCzGJtHntThLF4qIiULWeo,61
10
- airbyte_cdk/connector_builder/connector_builder_handler.py,sha256=nifmVvtl_CEwlKwzsCZQ6YALXaRoGOF0XfBCiFUfjJE,5168
11
- airbyte_cdk/connector_builder/main.py,sha256=YnOgXuY9O2SwAtrbhzoOTI8oN8tGERJWQdnl1Bm5HOw,3839
10
+ airbyte_cdk/connector_builder/connector_builder_handler.py,sha256=gwFpZHmvFrMB9NMlRuRfq0KEkbPaFucCB8k1DL20Wmw,5769
11
+ airbyte_cdk/connector_builder/main.py,sha256=7hE4GG8yTLSas_nUuANsPJQVBZyOK-l_1Q0vf0FjY5o,3839
12
12
  airbyte_cdk/connector_builder/models.py,sha256=9pIZ98LW_d6fRS39VdnUOf3cxGt4TkC5MJ0_OrzcCRk,1578
13
13
  airbyte_cdk/connector_builder/test_reader/__init__.py,sha256=iTwBMoI9vaJotEgpqZbFjlxRcbxXYypSVJ9YxeHk7wc,120
14
14
  airbyte_cdk/connector_builder/test_reader/helpers.py,sha256=Iczn-_iczS2CaIAunWwyFcX0uLTra8Wh9JVfzm1Gfxo,26765
@@ -71,7 +71,7 @@ airbyte_cdk/sources/declarative/concurrent_declarative_source.py,sha256=uhy0dRkA
71
71
  airbyte_cdk/sources/declarative/datetime/__init__.py,sha256=4Hw-PX1-VgESLF16cDdvuYCzGJtHntThLF4qIiULWeo,61
72
72
  airbyte_cdk/sources/declarative/datetime/datetime_parser.py,sha256=_zGNGq31RNy_0QBLt_EcTvgPyhj7urPdx6oA3M5-r3o,3150
73
73
  airbyte_cdk/sources/declarative/datetime/min_max_datetime.py,sha256=0BHBtDNQZfvwM45-tY5pNlTcKAFSGGNxemoi0Jic-0E,5785
74
- airbyte_cdk/sources/declarative/declarative_component_schema.yaml,sha256=-7gyAzojFjdkQ0IyKUwYyT91uwSSRO2pstlVjHyEaGc,158041
74
+ airbyte_cdk/sources/declarative/declarative_component_schema.yaml,sha256=twYvmNco0B7R8N5QXcTc1tbqWFB_7b-_i149LJbMss8,153129
75
75
  airbyte_cdk/sources/declarative/declarative_source.py,sha256=nF7wBqFd3AQmEKAm4CnIo29CJoQL562cJGSCeL8U8bA,1531
76
76
  airbyte_cdk/sources/declarative/declarative_stream.py,sha256=dCRlddBUSaJmBNBz1pSO1r2rTw8AP5d2_vlmIeGs2gg,10767
77
77
  airbyte_cdk/sources/declarative/decoders/__init__.py,sha256=JHb_0d3SE6kNY10mxA5YBEKPeSbsWYjByq1gUQxepoE,953
@@ -109,18 +109,18 @@ airbyte_cdk/sources/declarative/interpolation/interpolated_string.py,sha256=CQkH
109
109
  airbyte_cdk/sources/declarative/interpolation/interpolation.py,sha256=9IoeuWam3L6GyN10L6U8xNWXmkt9cnahSDNkez1OmFY,982
110
110
  airbyte_cdk/sources/declarative/interpolation/jinja.py,sha256=UQeuS4Vpyp4hlOn-R3tRyeBX0e9IoV6jQ6gH-Jz8lY0,7182
111
111
  airbyte_cdk/sources/declarative/interpolation/macros.py,sha256=CF2L_r73TCd1Wssq9_tjFPb4c872QM8oW6NL-DIR0h4,5226
112
- airbyte_cdk/sources/declarative/manifest_declarative_source.py,sha256=kFfyVpX-babuF4YzUHm7xfx_3M4M-GwJsrOWuez1z9Q,18894
112
+ airbyte_cdk/sources/declarative/manifest_declarative_source.py,sha256=tUe54Xgy7dq-a7HNaPogk6AXlVeqQXHWde6_8_Xy0ow,19130
113
113
  airbyte_cdk/sources/declarative/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
114
114
  airbyte_cdk/sources/declarative/migrations/legacy_to_per_partition_state_migration.py,sha256=iemy3fKLczcU0-Aor7tx5jcT6DRedKMqyK7kCOp01hg,3924
115
115
  airbyte_cdk/sources/declarative/migrations/state_migration.py,sha256=KWPjealMLKSMtajXgkdGgKg7EmTLR-CqqD7UIh0-eDU,794
116
116
  airbyte_cdk/sources/declarative/models/__init__.py,sha256=nUFxNCiKeYRVXuZEKA7GD-lTHxsiKcQ8FitZjKhPIvE,100
117
- airbyte_cdk/sources/declarative/models/declarative_component_schema.py,sha256=NYVuwCA-ot13weNOCc0_0DTjhiMUR8eHsRFdtrANnRo,111561
117
+ airbyte_cdk/sources/declarative/models/declarative_component_schema.py,sha256=nzQqJjBo8wFUF9gqF9E52zDsEDQGpG46aWylViTcAJU,108372
118
118
  airbyte_cdk/sources/declarative/parsers/__init__.py,sha256=ZnqYNxHsKCgO38IwB34RQyRMXTs4GTvlRi3ImKnIioo,61
119
119
  airbyte_cdk/sources/declarative/parsers/custom_code_compiler.py,sha256=nlVvHC511NUyDEEIRBkoeDTAvLqKNp-hRy8D19z8tdk,5941
120
120
  airbyte_cdk/sources/declarative/parsers/custom_exceptions.py,sha256=Rir9_z3Kcd5Es0-LChrzk-0qubAsiK_RSEnLmK2OXm8,553
121
- airbyte_cdk/sources/declarative/parsers/manifest_component_transformer.py,sha256=CXwTfD3wSQq3okcqwigpprbHhSURUokh4GK2OmOyKC8,9132
121
+ airbyte_cdk/sources/declarative/parsers/manifest_component_transformer.py,sha256=4C15MKV-zOrMVQAm4FyohDsrJUBCSpMv5tZw0SK3aeI,9685
122
122
  airbyte_cdk/sources/declarative/parsers/manifest_reference_resolver.py,sha256=IWUOdF03o-aQn0Occo1BJCxU0Pz-QILk5L67nzw2thw,6803
123
- airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py,sha256=64HO1wnBw5NjitXgYn3e-GVfum0zrQrpmLGlzC3mLJg,157514
123
+ airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py,sha256=APJkP5dmDU4aIaj7w3quGjrP1cV3MMp2gxbTckhOVRA,149720
124
124
  airbyte_cdk/sources/declarative/partition_routers/__init__.py,sha256=TBC9AkGaUqHm2IKHMPN6punBIcY5tWGULowcLoAVkfw,1109
125
125
  airbyte_cdk/sources/declarative/partition_routers/async_job_partition_router.py,sha256=VelO7zKqKtzMJ35jyFeg0ypJLQC0plqqIBNXoBW1G2E,3001
126
126
  airbyte_cdk/sources/declarative/partition_routers/cartesian_product_stream_slicer.py,sha256=c5cuVFM6NFkuQqG8Z5IwkBuwDrvXZN1CunUOM_L0ezg,6892
@@ -156,18 +156,13 @@ airbyte_cdk/sources/declarative/requesters/paginators/strategies/offset_incremen
156
156
  airbyte_cdk/sources/declarative/requesters/paginators/strategies/page_increment.py,sha256=Z2i6a-oKMmOTxHxsTVSnyaShkJ3u8xZw1xIJdx2yxss,2731
157
157
  airbyte_cdk/sources/declarative/requesters/paginators/strategies/pagination_strategy.py,sha256=ZBshGQNr5Bb_V8dqnWRISqdXFcjm1CKIXnlfbRhNl8g,1308
158
158
  airbyte_cdk/sources/declarative/requesters/paginators/strategies/stop_condition.py,sha256=LoKXdUbSgHEtSwtA8DFrnX6SpQbRVVwreY8NguTKTcI,2229
159
- airbyte_cdk/sources/declarative/requesters/query_properties/__init__.py,sha256=6Da7wsYQxzWWgpkisj47YbMPtj1sgg1b_60qTspO_Pw,604
160
- airbyte_cdk/sources/declarative/requesters/query_properties/group_by_key.py,sha256=7uVXFwzR5Q5ngkwAtW8x3QBK963Ub1Qpo2vapF8IIc0,659
161
- airbyte_cdk/sources/declarative/requesters/query_properties/properties_from_endpoint.py,sha256=Rz4CViWqDGKCCZ8eYbb5yVlF-ElXmBmMZqhYglFxGqA,1395
162
- airbyte_cdk/sources/declarative/requesters/query_properties/property_chunking.py,sha256=o9Jq-7mBC8ahPii5EngA0h4gBB8UV0xxZbifG9otrIk,2254
163
- airbyte_cdk/sources/declarative/requesters/query_properties/query_properties.py,sha256=6xULj0wzHzc8l6jV-v-fOtbeli8peBfvyeSLtioN0-0,1672
164
159
  airbyte_cdk/sources/declarative/requesters/request_option.py,sha256=Bl0gxGWudmwT3FXBozTN00WYle2jd6ry_S1YylCnwqM,4825
165
160
  airbyte_cdk/sources/declarative/requesters/request_options/__init__.py,sha256=WCwpKqM4wKqy-DHJaCHbKAlFqRVOqMi9K5qonxIfi_Y,809
166
161
  airbyte_cdk/sources/declarative/requesters/request_options/datetime_based_request_options_provider.py,sha256=31nG6_0igidJFQon37-WeQkTpG3g2A5ZmlluI3ilZdE,3632
167
162
  airbyte_cdk/sources/declarative/requesters/request_options/default_request_options_provider.py,sha256=SRROdPJZ5kuqHLOlkh115pWP9nDGfDxRYPgH9oD3hPo,1798
168
163
  airbyte_cdk/sources/declarative/requesters/request_options/interpolated_nested_request_input_provider.py,sha256=86YozYuBDfu0t9NbevIvQoGU0vqTP4rt3dRSTsHz3PA,2269
169
164
  airbyte_cdk/sources/declarative/requesters/request_options/interpolated_request_input_provider.py,sha256=rR00kE64U2yL0McU1gPr4_W5_sLUqwDgL3Nvj691nRU,2884
170
- airbyte_cdk/sources/declarative/requesters/request_options/interpolated_request_options_provider.py,sha256=dRlG1IyEOVzWFw7wm-8TBPn7JUtZw3jz6oAoH5yuuf0,6375
165
+ airbyte_cdk/sources/declarative/requesters/request_options/interpolated_request_options_provider.py,sha256=vOsdHfWHiTFc89WENHPv1hcxLgdzycMXVT_IEtLuhfs,5012
171
166
  airbyte_cdk/sources/declarative/requesters/request_options/request_options_provider.py,sha256=8YRiDzjYvqJ-aMmKFcjqzv_-e8OZ5QG_TbpZ-nuCu6s,2590
172
167
  airbyte_cdk/sources/declarative/requesters/request_path.py,sha256=S3MeFvcaQrMbOkSY2W2VbXLNomqt_3eXqVd9ZhgNwUs,299
173
168
  airbyte_cdk/sources/declarative/requesters/requester.py,sha256=OcDzuCBgD1owK_lBPG0KbRRHRn9kzbuRveU4HejDiv4,5116
@@ -178,7 +173,7 @@ airbyte_cdk/sources/declarative/resolvers/http_components_resolver.py,sha256=Aio
178
173
  airbyte_cdk/sources/declarative/retrievers/__init__.py,sha256=nQepwG_RfW53sgwvK5dLPqfCx0VjsQ83nYoPjBMAaLM,527
179
174
  airbyte_cdk/sources/declarative/retrievers/async_retriever.py,sha256=6oZtnCHm9NdDvjTSrVwPQOXGSdETSIR7eWH2vFjM7jI,4855
180
175
  airbyte_cdk/sources/declarative/retrievers/retriever.py,sha256=XPLs593Xv8c5cKMc37XzUAYmzlXd1a7eSsspM-CMuWA,1696
181
- airbyte_cdk/sources/declarative/retrievers/simple_retriever.py,sha256=QjkKOvvuP62f9J4RcfKTSYCP69lJBndhJCTdeRXO0LQ,31090
176
+ airbyte_cdk/sources/declarative/retrievers/simple_retriever.py,sha256=p6O4FYS7zzPq6uQT2NVnughUjI66tePaXVlyhCAyyv0,27746
182
177
  airbyte_cdk/sources/declarative/schema/__init__.py,sha256=xU45UvM5O4c1PSM13UHpCdh5hpW3HXy9vRRGEiAC1rg,795
183
178
  airbyte_cdk/sources/declarative/schema/default_schema_loader.py,sha256=KTACrIE23a83wsm3Rd9Eb4K6-20lrGqYxTHNp9yxsso,1820
184
179
  airbyte_cdk/sources/declarative/schema/dynamic_schema_loader.py,sha256=J8Q_iJYhcSQLWyt0bTZCbDAGpxt9G8FCc6Q9jtGsNzw,10703
@@ -191,7 +186,7 @@ airbyte_cdk/sources/declarative/stream_slicers/__init__.py,sha256=sI9vhc95RwJYOn
191
186
  airbyte_cdk/sources/declarative/stream_slicers/declarative_partition_generator.py,sha256=RW1Q44ml-VWeMl4lNcV6EfyzrzCZkjj-hd0Omx_n_n4,3405
192
187
  airbyte_cdk/sources/declarative/stream_slicers/stream_slicer.py,sha256=SOkIPBi2Wu7yxIvA15yFzUAB95a3IzA8LPq5DEqHQQc,725
193
188
  airbyte_cdk/sources/declarative/transformations/__init__.py,sha256=CPJ8TlMpiUmvG3624VYu_NfTzxwKcfBjM2Q2wJ7fkSA,919
194
- airbyte_cdk/sources/declarative/transformations/add_fields.py,sha256=vxLh0ekB0i_m8GYFpSad9T4S7eRxxtqZaigHLGVoltA,5366
189
+ airbyte_cdk/sources/declarative/transformations/add_fields.py,sha256=Eg1jQtRObgzxbtySTQs5uEZIjEklsoHFxYSPf78x6Ng,5420
195
190
  airbyte_cdk/sources/declarative/transformations/dpath_flatten_fields.py,sha256=I8oXPAOFhBV1mW_ufMn8Ii7oMbtect0sfLcpBNrKzzw,2374
196
191
  airbyte_cdk/sources/declarative/transformations/flatten_fields.py,sha256=yT3owG6rMKaRX-LJ_T-jSTnh1B5NoAHyH4YZN9yOvE8,1758
197
192
  airbyte_cdk/sources/declarative/transformations/keys_replace_transformation.py,sha256=vbIn6ump-Ut6g20yMub7PFoPBhOKVtrHSAUdcOUdLfw,1999
@@ -364,9 +359,9 @@ airbyte_cdk/utils/slice_hasher.py,sha256=EDxgROHDbfG-QKQb59m7h_7crN1tRiawdf5uU7G
364
359
  airbyte_cdk/utils/spec_schema_transformations.py,sha256=-5HTuNsnDBAhj-oLeQXwpTGA0HdcjFOf2zTEMUTTg_Y,816
365
360
  airbyte_cdk/utils/stream_status_utils.py,sha256=ZmBoiy5HVbUEHAMrUONxZvxnvfV9CesmQJLDTAIWnWw,1171
366
361
  airbyte_cdk/utils/traced_exception.py,sha256=C8uIBuCL_E4WnBAOPSxBicD06JAldoN9fGsQDp463OY,6292
367
- airbyte_cdk-6.43.0.dev0.dist-info/LICENSE.txt,sha256=Wfe61S4BaGPj404v8lrAbvhjYR68SHlkzeYrg3_bbuM,1051
368
- airbyte_cdk-6.43.0.dev0.dist-info/LICENSE_SHORT,sha256=aqF6D1NcESmpn-cqsxBtszTEnHKnlsp8L4x9wAh3Nxg,55
369
- airbyte_cdk-6.43.0.dev0.dist-info/METADATA,sha256=Gkcyw6S5UfIDRNpbltYuPPi5GdcRkjEv0DaPDpChh9g,6076
370
- airbyte_cdk-6.43.0.dev0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
371
- airbyte_cdk-6.43.0.dev0.dist-info/entry_points.txt,sha256=fj-e3PAQvsxsQzyyq8UkG1k8spunWnD4BAH2AwlR6NM,95
372
- airbyte_cdk-6.43.0.dev0.dist-info/RECORD,,
362
+ airbyte_cdk-6.43.1.dist-info/LICENSE.txt,sha256=Wfe61S4BaGPj404v8lrAbvhjYR68SHlkzeYrg3_bbuM,1051
363
+ airbyte_cdk-6.43.1.dist-info/LICENSE_SHORT,sha256=aqF6D1NcESmpn-cqsxBtszTEnHKnlsp8L4x9wAh3Nxg,55
364
+ airbyte_cdk-6.43.1.dist-info/METADATA,sha256=Zrfti0WPq-_VsjOASQALX5Gctg83yqECVMd-zOsyLOM,6071
365
+ airbyte_cdk-6.43.1.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
366
+ airbyte_cdk-6.43.1.dist-info/entry_points.txt,sha256=fj-e3PAQvsxsQzyyq8UkG1k8spunWnD4BAH2AwlR6NM,95
367
+ airbyte_cdk-6.43.1.dist-info/RECORD,,
@@ -1,14 +0,0 @@
1
- # Copyright (c) 2025 Airbyte, Inc., all rights reserved.
2
-
3
- from airbyte_cdk.sources.declarative.requesters.query_properties.group_by_key import GroupByKey
4
- from airbyte_cdk.sources.declarative.requesters.query_properties.properties_from_endpoint import (
5
- PropertiesFromEndpoint,
6
- )
7
- from airbyte_cdk.sources.declarative.requesters.query_properties.property_chunking import (
8
- PropertyChunking,
9
- )
10
- from airbyte_cdk.sources.declarative.requesters.query_properties.query_properties import (
11
- QueryProperties,
12
- )
13
-
14
- __all__ = ["GroupByKey", "PropertiesFromEndpoint", "PropertyChunking", "QueryProperties"]
@@ -1,24 +0,0 @@
1
- # Copyright (c) 2025 Airbyte, Inc., all rights reserved.
2
-
3
- from dataclasses import InitVar, dataclass
4
- from typing import Any, List, Mapping, Union
5
-
6
- from airbyte_cdk.sources.types import Config, Record
7
-
8
-
9
- @dataclass
10
- class GroupByKey:
11
- """
12
- tbd
13
- """
14
-
15
- key: Union[str, List[str]]
16
- parameters: InitVar[Mapping[str, Any]]
17
- config: Config
18
-
19
- def __post_init__(self, parameters: Mapping[str, Any]) -> None:
20
- self._keys = [self.key] if isinstance(self.key, str) else self.key
21
-
22
- def get_group_key(self, record: Record) -> str:
23
- resolved_keys = [str(record.data.get(key)) for key in self._keys]
24
- return ",".join(resolved_keys)
@@ -1,40 +0,0 @@
1
- # Copyright (c) 2025 Airbyte, Inc., all rights reserved.
2
-
3
- from dataclasses import InitVar, dataclass
4
- from typing import Any, Iterable, List, Mapping, Optional, Union
5
-
6
- import dpath
7
-
8
- from airbyte_cdk.sources.declarative.interpolation import InterpolatedString
9
- from airbyte_cdk.sources.declarative.retrievers import Retriever
10
- from airbyte_cdk.sources.types import Config, StreamSlice
11
-
12
-
13
- @dataclass
14
- class PropertiesFromEndpoint:
15
- """
16
- tbd
17
- """
18
-
19
- property_field_path: List[str]
20
- retriever: Retriever
21
- config: Config
22
- parameters: InitVar[Mapping[str, Any]]
23
-
24
- def __post_init__(self, parameters: Mapping[str, Any]) -> None:
25
- self._property_field_path = [
26
- InterpolatedString(string=property_field, parameters=parameters)
27
- for property_field in self.property_field_path
28
- ]
29
-
30
- def get_properties_from_endpoint(self, stream_slice: Optional[StreamSlice]) -> Iterable[str]:
31
- response_properties = self.retriever.read_records(
32
- records_schema={}, stream_slice=stream_slice
33
- )
34
- for property_obj in response_properties:
35
- path = [
36
- node.eval(self.config) if not isinstance(node, str) else node
37
- for node in self._property_field_path
38
- ]
39
-
40
- yield dpath.get(property_obj, path) # type: ignore # extracted will be a MutableMapping, given input data structure
@@ -1,65 +0,0 @@
1
- # Copyright (c) 2025 Airbyte, Inc., all rights reserved.
2
-
3
- from dataclasses import InitVar, dataclass
4
- from enum import Enum
5
- from typing import Any, Iterable, List, Mapping, Optional
6
-
7
- from airbyte_cdk.sources.declarative.requesters.query_properties import GroupByKey
8
- from airbyte_cdk.sources.types import Config, Record
9
-
10
-
11
- class PropertyLimitType(Enum):
12
- """
13
- yeah
14
- """
15
-
16
- characters = "characters"
17
- property_count = "property_count"
18
-
19
-
20
- @dataclass
21
- class PropertyChunking:
22
- """
23
- tbd
24
- """
25
-
26
- property_limit_type: PropertyLimitType
27
- property_limit: Optional[int]
28
- record_merge_strategy: Optional[
29
- GroupByKey
30
- ] # This should eventually be some sort of interface or type
31
- parameters: InitVar[Mapping[str, Any]]
32
- config: Config
33
-
34
- def __post_init__(self, parameters: Mapping[str, Any]) -> None:
35
- self._record_merge_strategy = self.record_merge_strategy or GroupByKey(
36
- key="id", config=self.config, parameters=parameters
37
- )
38
-
39
- def get_request_property_chunks(
40
- self, property_fields: Iterable[str], always_include_properties: Optional[List[str]]
41
- ) -> Iterable[List[str]]:
42
- if not self.property_limit:
43
- single_property_chunk = list(property_fields)
44
- if always_include_properties:
45
- single_property_chunk.extend(always_include_properties)
46
- yield single_property_chunk
47
- return
48
- current_chunk = list(always_include_properties) if always_include_properties else []
49
- chunk_size = 0
50
- for property_field in property_fields:
51
- property_field_size = (
52
- len(property_field)
53
- if self.property_limit_type == PropertyLimitType.characters
54
- else 1
55
- )
56
- if chunk_size + property_field_size > self.property_limit:
57
- yield current_chunk
58
- current_chunk = list(always_include_properties) if always_include_properties else []
59
- chunk_size = 0
60
- current_chunk.append(property_field)
61
- chunk_size += property_field_size
62
- yield current_chunk
63
-
64
- def get_merge_key(self, record: Record) -> str:
65
- return self._record_merge_strategy.get_group_key(record=record)
@@ -1,48 +0,0 @@
1
- # Copyright (c) 2025 Airbyte, Inc., all rights reserved.
2
-
3
- from dataclasses import InitVar, dataclass
4
- from typing import Any, Iterable, List, Mapping, Optional, Union
5
-
6
- from airbyte_cdk.sources.declarative.requesters.query_properties import (
7
- PropertiesFromEndpoint,
8
- PropertyChunking,
9
- )
10
- from airbyte_cdk.sources.types import Config, StreamSlice
11
-
12
-
13
- @dataclass
14
- class QueryProperties:
15
- """
16
- tbd
17
- """
18
-
19
- property_list: Optional[Union[List[str], PropertiesFromEndpoint]]
20
- always_include_properties: Optional[List[str]]
21
- property_chunking: Optional[PropertyChunking]
22
- config: Config
23
- parameters: InitVar[Mapping[str, Any]]
24
-
25
- def get_request_property_chunks(
26
- self, stream_slice: Optional[StreamSlice] = None
27
- ) -> Iterable[List[str]]:
28
- fields: Union[Iterable[str], List[str]]
29
- if isinstance(self.property_list, PropertiesFromEndpoint):
30
- fields = self.property_list.get_properties_from_endpoint(stream_slice=stream_slice)
31
- else:
32
- fields = self.property_list if self.property_list else []
33
-
34
- if self.property_chunking:
35
- yield from self.property_chunking.get_request_property_chunks(
36
- property_fields=fields, always_include_properties=self.always_include_properties
37
- )
38
- else:
39
- yield from [list(fields)]
40
-
41
- def has_multiple_chunks(self, stream_slice: Optional[StreamSlice]) -> bool:
42
- property_chunks = iter(self.get_request_property_chunks(stream_slice=stream_slice))
43
- try:
44
- next(property_chunks)
45
- next(property_chunks)
46
- return True
47
- except StopIteration:
48
- return False