airbyte-cdk 6.48.1__py3-none-any.whl → 6.48.2__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.
@@ -4,6 +4,7 @@
4
4
 
5
5
 
6
6
  import logging
7
+ from math import log
7
8
  from typing import Any, ClassVar, Dict, Iterator, List, Mapping, Optional, Union
8
9
 
9
10
  from airbyte_cdk.connector_builder.models import (
@@ -112,11 +113,16 @@ class TestReader:
112
113
  record_limit = self._check_record_limit(record_limit)
113
114
  # The connector builder currently only supports reading from a single stream at a time
114
115
  stream = source.streams(config)[0]
116
+
117
+ # get any deprecation warnings during the component creation
118
+ deprecation_warnings: List[LogMessage] = source.deprecation_warnings()
119
+
115
120
  schema_inferrer = SchemaInferrer(
116
121
  self._pk_to_nested_and_composite_field(stream.primary_key),
117
122
  self._cursor_field_to_nested_and_composite_field(stream.cursor_field),
118
123
  )
119
124
  datetime_format_inferrer = DatetimeFormatInferrer()
125
+
120
126
  message_group = get_message_groups(
121
127
  self._read_stream(source, config, configured_catalog, state),
122
128
  schema_inferrer,
@@ -127,6 +133,10 @@ class TestReader:
127
133
  slices, log_messages, auxiliary_requests, latest_config_update = self._categorise_groups(
128
134
  message_group
129
135
  )
136
+
137
+ # extend log messages with deprecation warnings
138
+ log_messages.extend(deprecation_warnings)
139
+
130
140
  schema, log_messages = self._get_infered_schema(
131
141
  configured_catalog, schema_inferrer, log_messages
132
142
  )
@@ -269,6 +279,7 @@ class TestReader:
269
279
  auxiliary_requests = []
270
280
  latest_config_update: Optional[AirbyteControlMessage] = None
271
281
 
282
+ # process the message groups first
272
283
  for message_group in message_groups:
273
284
  match message_group:
274
285
  case AirbyteLogMessage():
@@ -3,7 +3,7 @@
3
3
  #
4
4
 
5
5
  manifest_migrations:
6
- - version: 6.47.1
6
+ - version: 6.48.2
7
7
  migrations:
8
8
  - name: http_requester_url_base_to_url
9
9
  order: 1
@@ -1911,15 +1911,16 @@ definitions:
1911
1911
  type: object
1912
1912
  required:
1913
1913
  - type
1914
- - url_base
1915
1914
  properties:
1916
1915
  type:
1917
1916
  type: string
1918
1917
  enum: [HttpRequester]
1919
1918
  url_base:
1920
- linkable: true
1919
+ deprecated: true
1920
+ deprecation_message: "Use `url` field instead."
1921
1921
  title: API Base URL
1922
- description: The Base URL of the API source. Do not put sensitive information (e.g. API tokens) into this field - Use the Authentication component for this.
1922
+ description: Deprecated, use the `url` instead. Base URL of the API source. Do not put sensitive information (e.g. API tokens) into this field - Use the Authentication component for this.
1923
+ linkable: true
1923
1924
  type: string
1924
1925
  interpolation_context:
1925
1926
  - config
@@ -1935,9 +1936,29 @@ definitions:
1935
1936
  - "{{ config['base_url'] or 'https://app.posthog.com'}}/api"
1936
1937
  - "https://connect.squareup.com/v2/quotes/{{ stream_partition['id'] }}/quote_line_groups"
1937
1938
  - "https://example.com/api/v1/resource/{{ next_page_token['id'] }}"
1939
+ url:
1940
+ title: The URL of an API endpoint
1941
+ description: The URL of the API source. Do not put sensitive information (e.g. API tokens) into this field - Use the Authentication component for this.
1942
+ type: string
1943
+ interpolation_context:
1944
+ - config
1945
+ - next_page_token
1946
+ - stream_interval
1947
+ - stream_partition
1948
+ - stream_slice
1949
+ - creation_response
1950
+ - polling_response
1951
+ - download_target
1952
+ examples:
1953
+ - "https://connect.squareup.com/v2"
1954
+ - "{{ config['url'] or 'https://app.posthog.com'}}/api"
1955
+ - "https://connect.squareup.com/v2/quotes/{{ stream_partition['id'] }}/quote_line_groups"
1956
+ - "https://example.com/api/v1/resource/{{ next_page_token['id'] }}"
1938
1957
  path:
1958
+ deprecated: true
1959
+ deprecation_message: "Use `url` field instead."
1939
1960
  title: URL Path
1940
- description: The Path the specific API endpoint that this stream represents. Do not put sensitive information (e.g. API tokens) into this field - Use the Authentication component for this.
1961
+ description: Deprecated, use the `url` instead. Path the specific API endpoint that this stream represents. Do not put sensitive information (e.g. API tokens) into this field - Use the Authentication component for this.
1941
1962
  type: string
1942
1963
  interpolation_context:
1943
1964
  - config
@@ -1983,6 +2004,8 @@ definitions:
1983
2004
  description: Allows for retrieving a dynamic set of properties from an API endpoint which can be injected into outbound request using the stream_partition.extra_fields.
1984
2005
  "$ref": "#/definitions/PropertiesFromEndpoint"
1985
2006
  request_body_data:
2007
+ deprecated: true
2008
+ deprecation_message: "Use `request_body` field instead."
1986
2009
  title: Request Body Payload (Non-JSON)
1987
2010
  description: Specifies how to populate the body of the request with a non-JSON payload. Plain text will be sent as is, whereas objects will be converted to a urlencoded form.
1988
2011
  anyOf:
@@ -2001,6 +2024,8 @@ definitions:
2001
2024
  [{"value": {{ stream_interval['start_time'] | int * 1000 }} }]
2002
2025
  }, "orderBy": 1, "columnName": "Timestamp"}]/
2003
2026
  request_body_json:
2027
+ deprecated: true
2028
+ deprecation_message: "Use `request_body` field instead."
2004
2029
  title: Request Body JSON Payload
2005
2030
  description: Specifies how to populate the body of the request with a JSON payload. Can contain nested objects.
2006
2031
  anyOf:
@@ -2019,6 +2044,35 @@ definitions:
2019
2044
  - sort:
2020
2045
  field: "updated_at"
2021
2046
  order: "ascending"
2047
+ request_body:
2048
+ title: Request Body Payload to be send as a part of the API request.
2049
+ description: Specifies how to populate the body of the request with a payload. Can contain nested objects.
2050
+ anyOf:
2051
+ - "$ref": "#/definitions/RequestBody"
2052
+ interpolation_context:
2053
+ - next_page_token
2054
+ - stream_interval
2055
+ - stream_partition
2056
+ - stream_slice
2057
+ examples:
2058
+ - type: RequestBodyJson
2059
+ value:
2060
+ sort_order: "ASC"
2061
+ sort_field: "CREATED_AT"
2062
+ - type: RequestBodyJson
2063
+ value:
2064
+ key: "{{ config['value'] }}"
2065
+ - type: RequestBodyJson
2066
+ value:
2067
+ sort:
2068
+ field: "updated_at"
2069
+ order: "ascending"
2070
+ - type: RequestBodyData
2071
+ value: "plain_text_body"
2072
+ - type: RequestBodyData
2073
+ value:
2074
+ param1: "value1"
2075
+ param2: "{{ config['param2_value'] }}"
2022
2076
  request_headers:
2023
2077
  title: Request Headers
2024
2078
  description: Return any non-auth headers. Authentication headers will overwrite any overlapping headers returned from this method.
@@ -4019,6 +4073,27 @@ definitions:
4019
4073
  - type
4020
4074
  - stream_template
4021
4075
  - components_resolver
4076
+ RequestBody:
4077
+ type: object
4078
+ description: The request body payload. Can be either URL encoded data or JSON.
4079
+ properties:
4080
+ type:
4081
+ anyOf:
4082
+ - type: string
4083
+ enum: [RequestBodyData]
4084
+ - type: string
4085
+ enum: [RequestBodyJson]
4086
+ value:
4087
+ anyOf:
4088
+ - type: string
4089
+ description: The request body payload as a string.
4090
+ - type: object
4091
+ description: The request body payload as a Non-JSON object (url-encoded data).
4092
+ additionalProperties:
4093
+ type: string
4094
+ - type: object
4095
+ description: The request body payload as a JSON object (json-encoded data).
4096
+ additionalProperties: true
4022
4097
  interpolation:
4023
4098
  variables:
4024
4099
  - title: config
@@ -4227,4 +4302,4 @@ interpolation:
4227
4302
  regex: The regular expression to search for. It must include a capture group.
4228
4303
  return_type: str
4229
4304
  examples:
4230
- - '{{ "goodbye, cruel world" | regex_search("goodbye,\s(.*)$") }} -> "cruel world"'
4305
+ - '{{ "goodbye, cruel world" | regex_search("goodbye,\s(.*)$") }} -> "cruel world"'
@@ -4,8 +4,11 @@
4
4
 
5
5
  import logging
6
6
  from abc import abstractmethod
7
- from typing import Any, Mapping, Tuple
7
+ from typing import Any, List, Mapping, Tuple
8
8
 
9
+ from airbyte_cdk.connector_builder.models import (
10
+ LogMessage as ConnectorBuilderLogMessage,
11
+ )
9
12
  from airbyte_cdk.sources.abstract_source import AbstractSource
10
13
  from airbyte_cdk.sources.declarative.checks.connection_checker import ConnectionChecker
11
14
 
@@ -34,3 +37,9 @@ class DeclarativeSource(AbstractSource):
34
37
  The error object will be cast to string to display the problem to the user.
35
38
  """
36
39
  return self.connection_checker.check_connection(self, logger, config)
40
+
41
+ def deprecation_warnings(self) -> List[ConnectorBuilderLogMessage]:
42
+ """
43
+ Returns a list of deprecation warnings for the source.
44
+ """
45
+ return []
@@ -12,7 +12,7 @@ from airbyte_cdk.sources.types import Config
12
12
  NestedMappingEntry = Union[
13
13
  dict[str, "NestedMapping"], list["NestedMapping"], str, int, float, bool, None
14
14
  ]
15
- NestedMapping = Union[dict[str, NestedMappingEntry], str]
15
+ NestedMapping = Union[dict[str, NestedMappingEntry], str, dict[str, Any]]
16
16
 
17
17
 
18
18
  @dataclass
@@ -15,6 +15,9 @@ from jsonschema.exceptions import ValidationError
15
15
  from jsonschema.validators import validate
16
16
  from packaging.version import InvalidVersion, Version
17
17
 
18
+ from airbyte_cdk.connector_builder.models import (
19
+ LogMessage as ConnectorBuilderLogMessage,
20
+ )
18
21
  from airbyte_cdk.manifest_migrations.migration_handler import (
19
22
  ManifestMigrationHandler,
20
23
  )
@@ -230,6 +233,9 @@ class ManifestDeclarativeSource(DeclarativeSource):
230
233
  with_dynamic_stream_name=True,
231
234
  )
232
235
 
236
+ def deprecation_warnings(self) -> List[ConnectorBuilderLogMessage]:
237
+ return self._constructor.get_model_deprecations()
238
+
233
239
  @property
234
240
  def connection_checker(self) -> ConnectionChecker:
235
241
  check = self._source_config["check"]
@@ -0,0 +1,144 @@
1
+ # Copyright (c) 2025 Airbyte, Inc., all rights reserved.
2
+
3
+ # THIS IS A STATIC CLASS MODEL USED TO DISPLAY DEPRECATION WARNINGS
4
+ # WHEN DEPRECATED FIELDS ARE ACCESSED
5
+
6
+ import warnings
7
+ from typing import Any, List
8
+
9
+ from pydantic.v1 import BaseModel
10
+
11
+ from airbyte_cdk.connector_builder.models import LogMessage as ConnectorBuilderLogMessage
12
+
13
+ # format the warning message
14
+ warnings.formatwarning = (
15
+ lambda message, category, *args, **kwargs: f"{category.__name__}: {message}"
16
+ )
17
+
18
+ FIELDS_TAG = "__fields__"
19
+ DEPRECATED = "deprecated"
20
+ DEPRECATION_MESSAGE = "deprecation_message"
21
+ DEPRECATION_LOGS_TAG = "_deprecation_logs"
22
+
23
+
24
+ class BaseModelWithDeprecations(BaseModel):
25
+ """
26
+ Pydantic BaseModel that warns when deprecated fields are accessed.
27
+ The deprecation message is stored in the field's extra attributes.
28
+ This class is used to create models that can have deprecated fields
29
+ and show warnings when those fields are accessed or initialized.
30
+
31
+ The `_deprecation_logs` attribute is stored in the model itself.
32
+ The collected deprecation warnings are further propagated to the Airbyte log messages,
33
+ during the component creation process, in `model_to_component._collect_model_deprecations()`.
34
+
35
+ The component implementation is not responsible for handling the deprecation warnings,
36
+ since the deprecation warnings are already handled in the model itself.
37
+ """
38
+
39
+ class Config:
40
+ """
41
+ Allow extra fields in the model. In case the model restricts extra fields.
42
+ """
43
+
44
+ extra = "allow"
45
+
46
+ def __init__(self, **model_fields: Any) -> None:
47
+ """
48
+ Show warnings for deprecated fields during component initialization.
49
+ """
50
+ # call the parent constructor first to initialize Pydantic internals
51
+ super().__init__(**model_fields)
52
+ # set the placeholder for the default deprecation messages
53
+ self._default_deprecation_messages: List[str] = []
54
+ # set the placeholder for the deprecation logs
55
+ self._deprecation_logs: List[ConnectorBuilderLogMessage] = []
56
+ # process deprecated fields, if present
57
+ self._process_fields(model_fields)
58
+ # emit default deprecation messages
59
+ self._emit_default_deprecation_messages()
60
+ # set the deprecation logs attribute to the model
61
+ self._set_deprecation_logs_attr_to_model()
62
+
63
+ def _is_deprecated_field(self, field_name: str) -> bool:
64
+ return (
65
+ self.__fields__[field_name].field_info.extra.get(DEPRECATED, False)
66
+ if field_name in self.__fields__.keys()
67
+ else False
68
+ )
69
+
70
+ def _get_deprecation_message(self, field_name: str) -> str:
71
+ return (
72
+ self.__fields__[field_name].field_info.extra.get(
73
+ DEPRECATION_MESSAGE, "<missing_deprecation_message>"
74
+ )
75
+ if field_name in self.__fields__.keys()
76
+ else "<missing_deprecation_message>"
77
+ )
78
+
79
+ def _process_fields(self, model_fields: Any) -> None:
80
+ """
81
+ Processes the fields in the provided model data, checking for deprecated fields.
82
+
83
+ For each field in the input `model_fields`, this method checks if the field exists in the model's defined fields.
84
+ If the field is marked as deprecated (using the `DEPRECATED` flag in its metadata), it triggers a deprecation warning
85
+ by calling the `_create_warning` method with the field name and an optional deprecation message.
86
+
87
+ Args:
88
+ model_fields (Any): The data containing fields to be processed.
89
+
90
+ Returns:
91
+ None
92
+ """
93
+
94
+ if hasattr(self, FIELDS_TAG):
95
+ for field_name in model_fields.keys():
96
+ if self._is_deprecated_field(field_name):
97
+ self._create_warning(
98
+ field_name,
99
+ self._get_deprecation_message(field_name),
100
+ )
101
+
102
+ def _set_deprecation_logs_attr_to_model(self) -> None:
103
+ """
104
+ Sets the deprecation logs attribute on the model instance.
105
+
106
+ This method attaches the current instance's deprecation logs to the model by setting
107
+ an attribute named by `DEPRECATION_LOGS_TAG` to the value of `self._deprecation_logs`.
108
+ This is typically used to track or log deprecated features or configurations within the model.
109
+
110
+ Returns:
111
+ None
112
+ """
113
+ setattr(self, DEPRECATION_LOGS_TAG, self._deprecation_logs)
114
+
115
+ def _create_warning(self, field_name: str, message: str) -> None:
116
+ """
117
+ Show a warning message for deprecated fields (to stdout).
118
+ Args:
119
+ field_name (str): Name of the deprecated field.
120
+ message (str): Warning message to be displayed.
121
+ """
122
+
123
+ deprecated_message = f"Component type: `{self.__class__.__name__}`. Field '{field_name}' is deprecated. {message}"
124
+
125
+ if deprecated_message not in self._default_deprecation_messages:
126
+ # Avoid duplicates in the default deprecation messages
127
+ self._default_deprecation_messages.append(deprecated_message)
128
+
129
+ # Create an Airbyte deprecation log message
130
+ deprecation_log_message = ConnectorBuilderLogMessage(
131
+ level="WARN", message=deprecated_message
132
+ )
133
+ # Add the deprecation message to the Airbyte log messages,
134
+ # this logs are displayed in the Connector Builder.
135
+ if deprecation_log_message not in self._deprecation_logs:
136
+ # Avoid duplicates in the deprecation logs
137
+ self._deprecation_logs.append(deprecation_log_message)
138
+
139
+ def _emit_default_deprecation_messages(self) -> None:
140
+ """
141
+ Emit default deprecation messages for deprecated fields to STDOUT.
142
+ """
143
+ for message in self._default_deprecation_messages:
144
+ warnings.warn(message, DeprecationWarning)
@@ -10,6 +10,10 @@ from typing import Any, Dict, List, Literal, Optional, Union
10
10
 
11
11
  from pydantic.v1 import BaseModel, Extra, Field
12
12
 
13
+ from airbyte_cdk.sources.declarative.models.base_model_with_deprecations import (
14
+ BaseModelWithDeprecations,
15
+ )
16
+
13
17
 
14
18
  class AuthFlowType(Enum):
15
19
  oauth2_0 = "oauth2.0"
@@ -1497,6 +1501,11 @@ class ConfigComponentsResolver(BaseModel):
1497
1501
  parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
1498
1502
 
1499
1503
 
1504
+ class RequestBody(BaseModel):
1505
+ type: Optional[Union[Literal["RequestBodyData"], Literal["RequestBodyJson"]]] = None
1506
+ value: Optional[Union[str, Dict[str, str], Dict[str, Any]]] = None
1507
+
1508
+
1500
1509
  class AddedFieldDefinition(BaseModel):
1501
1510
  type: Literal["AddedFieldDefinition"]
1502
1511
  path: List[str] = Field(
@@ -2207,11 +2216,13 @@ class SessionTokenAuthenticator(BaseModel):
2207
2216
  parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
2208
2217
 
2209
2218
 
2210
- class HttpRequester(BaseModel):
2219
+ class HttpRequester(BaseModelWithDeprecations):
2211
2220
  type: Literal["HttpRequester"]
2212
- url_base: str = Field(
2213
- ...,
2214
- description="The Base URL of the API source. Do not put sensitive information (e.g. API tokens) into this field - Use the Authentication component for this.",
2221
+ url_base: Optional[str] = Field(
2222
+ None,
2223
+ deprecated=True,
2224
+ deprecation_message="Use `url` field instead.",
2225
+ description="Deprecated, use the `url` instead. Base URL of the API source. Do not put sensitive information (e.g. API tokens) into this field - Use the Authentication component for this.",
2215
2226
  examples=[
2216
2227
  "https://connect.squareup.com/v2",
2217
2228
  "{{ config['base_url'] or 'https://app.posthog.com'}}/api",
@@ -2220,9 +2231,22 @@ class HttpRequester(BaseModel):
2220
2231
  ],
2221
2232
  title="API Base URL",
2222
2233
  )
2234
+ url: Optional[str] = Field(
2235
+ None,
2236
+ description="The URL of the API source. Do not put sensitive information (e.g. API tokens) into this field - Use the Authentication component for this.",
2237
+ examples=[
2238
+ "https://connect.squareup.com/v2",
2239
+ "{{ config['url'] or 'https://app.posthog.com'}}/api",
2240
+ "https://connect.squareup.com/v2/quotes/{{ stream_partition['id'] }}/quote_line_groups",
2241
+ "https://example.com/api/v1/resource/{{ next_page_token['id'] }}",
2242
+ ],
2243
+ title="The URL of an API endpoint",
2244
+ )
2223
2245
  path: Optional[str] = Field(
2224
2246
  None,
2225
- description="The Path the specific API endpoint that this stream represents. Do not put sensitive information (e.g. API tokens) into this field - Use the Authentication component for this.",
2247
+ deprecated=True,
2248
+ deprecation_message="Use `url` field instead.",
2249
+ description="Deprecated, use the `url` instead. Path the specific API endpoint that this stream represents. Do not put sensitive information (e.g. API tokens) into this field - Use the Authentication component for this.",
2226
2250
  examples=[
2227
2251
  "/products",
2228
2252
  "/quotes/{{ stream_partition['id'] }}/quote_line_groups",
@@ -2261,6 +2285,8 @@ class HttpRequester(BaseModel):
2261
2285
  )
2262
2286
  request_body_data: Optional[Union[Dict[str, str], str]] = Field(
2263
2287
  None,
2288
+ deprecated=True,
2289
+ deprecation_message="Use `request_body` field instead.",
2264
2290
  description="Specifies how to populate the body of the request with a non-JSON payload. Plain text will be sent as is, whereas objects will be converted to a urlencoded form.",
2265
2291
  examples=[
2266
2292
  '[{"clause": {"type": "timestamp", "operator": 10, "parameters":\n [{"value": {{ stream_interval[\'start_time\'] | int * 1000 }} }]\n }, "orderBy": 1, "columnName": "Timestamp"}]/\n'
@@ -2269,6 +2295,8 @@ class HttpRequester(BaseModel):
2269
2295
  )
2270
2296
  request_body_json: Optional[Union[Dict[str, Any], str]] = Field(
2271
2297
  None,
2298
+ deprecated=True,
2299
+ deprecation_message="Use `request_body` field instead.",
2272
2300
  description="Specifies how to populate the body of the request with a JSON payload. Can contain nested objects.",
2273
2301
  examples=[
2274
2302
  {"sort_order": "ASC", "sort_field": "CREATED_AT"},
@@ -2277,6 +2305,27 @@ class HttpRequester(BaseModel):
2277
2305
  ],
2278
2306
  title="Request Body JSON Payload",
2279
2307
  )
2308
+ request_body: Optional[RequestBody] = Field(
2309
+ None,
2310
+ description="Specifies how to populate the body of the request with a payload. Can contain nested objects.",
2311
+ examples=[
2312
+ {
2313
+ "type": "RequestBodyJson",
2314
+ "value": {"sort_order": "ASC", "sort_field": "CREATED_AT"},
2315
+ },
2316
+ {"type": "RequestBodyJson", "value": {"key": "{{ config['value'] }}"}},
2317
+ {
2318
+ "type": "RequestBodyJson",
2319
+ "value": {"sort": {"field": "updated_at", "order": "ascending"}},
2320
+ },
2321
+ {"type": "RequestBodyData", "value": "plain_text_body"},
2322
+ {
2323
+ "type": "RequestBodyData",
2324
+ "value": {"param1": "value1", "param2": "{{ config['param2_value'] }}"},
2325
+ },
2326
+ ],
2327
+ title="Request Body Payload to be send as a part of the API request.",
2328
+ )
2280
2329
  request_headers: Optional[Union[Dict[str, str], str]] = Field(
2281
2330
  None,
2282
2331
  description="Return any non-auth headers. Authentication headers will overwrite any overlapping headers returned from this method.",
@@ -27,6 +27,9 @@ from typing import (
27
27
  from isodate import parse_duration
28
28
  from pydantic.v1 import BaseModel
29
29
 
30
+ from airbyte_cdk.connector_builder.models import (
31
+ LogMessage as ConnectorBuilderLogMessage,
32
+ )
30
33
  from airbyte_cdk.models import FailureType, Level
31
34
  from airbyte_cdk.sources.connector_state_manager import ConnectorStateManager
32
35
  from airbyte_cdk.sources.declarative.async_job.job_orchestrator import AsyncJobOrchestrator
@@ -107,6 +110,10 @@ from airbyte_cdk.sources.declarative.migrations.legacy_to_per_partition_state_mi
107
110
  from airbyte_cdk.sources.declarative.models import (
108
111
  CustomStateMigration,
109
112
  )
113
+ from airbyte_cdk.sources.declarative.models.base_model_with_deprecations import (
114
+ DEPRECATION_LOGS_TAG,
115
+ BaseModelWithDeprecations,
116
+ )
110
117
  from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
111
118
  AddedFieldDefinition as AddedFieldDefinitionModel,
112
119
  )
@@ -593,6 +600,8 @@ class ModelToComponentFactory:
593
600
  self._connector_state_manager = connector_state_manager or ConnectorStateManager()
594
601
  self._api_budget: Optional[Union[APIBudget, HttpAPIBudget]] = None
595
602
  self._job_tracker: JobTracker = JobTracker(max_concurrent_async_job_count or 1)
603
+ # placeholder for deprecation warnings
604
+ self._collected_deprecation_logs: List[ConnectorBuilderLogMessage] = []
596
605
 
597
606
  def _init_mappings(self) -> None:
598
607
  self.PYDANTIC_MODEL_TO_CONSTRUCTOR: Mapping[Type[BaseModel], Callable[..., Any]] = {
@@ -740,8 +749,34 @@ class ModelToComponentFactory:
740
749
  component_constructor = self.PYDANTIC_MODEL_TO_CONSTRUCTOR.get(model.__class__)
741
750
  if not component_constructor:
742
751
  raise ValueError(f"Could not find constructor for {model.__class__}")
752
+
753
+ # collect deprecation warnings for supported models.
754
+ if isinstance(model, BaseModelWithDeprecations):
755
+ self._collect_model_deprecations(model)
756
+
743
757
  return component_constructor(model=model, config=config, **kwargs)
744
758
 
759
+ def get_model_deprecations(self) -> List[ConnectorBuilderLogMessage]:
760
+ """
761
+ Returns the deprecation warnings that were collected during the creation of components.
762
+ """
763
+ return self._collected_deprecation_logs
764
+
765
+ def _collect_model_deprecations(self, model: BaseModelWithDeprecations) -> None:
766
+ """
767
+ Collects deprecation logs from the given model and appends any new logs to the internal collection.
768
+
769
+ This method checks if the provided model has deprecation logs (identified by the presence of the DEPRECATION_LOGS_TAG attribute and a non-None `_deprecation_logs` property). It iterates through each deprecation log in the model and appends it to the `_collected_deprecation_logs` list if it has not already been collected, ensuring that duplicate logs are avoided.
770
+
771
+ Args:
772
+ model (BaseModelWithDeprecations): The model instance from which to collect deprecation logs.
773
+ """
774
+ if hasattr(model, DEPRECATION_LOGS_TAG) and model._deprecation_logs is not None:
775
+ for log in model._deprecation_logs:
776
+ # avoid duplicates for deprecation logs observed.
777
+ if log not in self._collected_deprecation_logs:
778
+ self._collected_deprecation_logs.append(log)
779
+
745
780
  @staticmethod
746
781
  def create_added_field_definition(
747
782
  model: AddedFieldDefinitionModel, config: Config, **kwargs: Any
@@ -2180,7 +2215,7 @@ class ModelToComponentFactory:
2180
2215
  self._create_component_from_model(
2181
2216
  model=model.authenticator,
2182
2217
  config=config,
2183
- url_base=model.url_base,
2218
+ url_base=model.url or model.url_base,
2184
2219
  name=name,
2185
2220
  decoder=decoder,
2186
2221
  )
@@ -2210,6 +2245,7 @@ class ModelToComponentFactory:
2210
2245
  request_parameters = model.request_parameters
2211
2246
 
2212
2247
  request_options_provider = InterpolatedRequestOptionsProvider(
2248
+ request_body=model.request_body,
2213
2249
  request_body_data=model.request_body_data,
2214
2250
  request_body_json=model.request_body_json,
2215
2251
  request_headers=model.request_headers,
@@ -2226,6 +2262,7 @@ class ModelToComponentFactory:
2226
2262
 
2227
2263
  return HttpRequester(
2228
2264
  name=name,
2265
+ url=model.url,
2229
2266
  url_base=model.url_base,
2230
2267
  path=model.path,
2231
2268
  authenticator=authenticator,
@@ -2934,6 +2971,25 @@ class ModelToComponentFactory:
2934
2971
  use_cache: Optional[bool] = None,
2935
2972
  **kwargs: Any,
2936
2973
  ) -> SimpleRetriever:
2974
+ def _get_url() -> str:
2975
+ """
2976
+ Closure to get the URL from the requester. This is used to get the URL in the case of a lazy retriever.
2977
+ This is needed because the URL is not set until the requester is created.
2978
+ """
2979
+
2980
+ _url = (
2981
+ model.requester.url
2982
+ if hasattr(model.requester, "url") and model.requester.url is not None
2983
+ else requester.get_url()
2984
+ )
2985
+ _url_base = (
2986
+ model.requester.url_base
2987
+ if hasattr(model.requester, "url_base") and model.requester.url_base is not None
2988
+ else requester.get_url_base()
2989
+ )
2990
+
2991
+ return _url or _url_base
2992
+
2937
2993
  decoder = (
2938
2994
  self._create_component_from_model(model=model.decoder, config=config)
2939
2995
  if model.decoder
@@ -3001,11 +3057,6 @@ class ModelToComponentFactory:
3001
3057
  use_cache=use_cache,
3002
3058
  config=config,
3003
3059
  )
3004
- url_base = (
3005
- model.requester.url_base
3006
- if hasattr(model.requester, "url_base")
3007
- else requester.get_url_base()
3008
- )
3009
3060
 
3010
3061
  # Define cursor only if per partition or common incremental support is needed
3011
3062
  cursor = stream_slicer if isinstance(stream_slicer, DeclarativeCursor) else None
@@ -3029,7 +3080,7 @@ class ModelToComponentFactory:
3029
3080
  self._create_component_from_model(
3030
3081
  model=model.paginator,
3031
3082
  config=config,
3032
- url_base=url_base,
3083
+ url_base=_get_url(),
3033
3084
  extractor_model=model.record_selector.extractor,
3034
3085
  decoder=decoder,
3035
3086
  cursor_used_for_stop_condition=cursor_used_for_stop_condition,
@@ -3,7 +3,6 @@
3
3
  #
4
4
 
5
5
  import logging
6
- import os
7
6
  from dataclasses import InitVar, dataclass, field
8
7
  from typing import Any, Callable, Mapping, MutableMapping, Optional, Union
9
8
  from urllib.parse import urljoin
@@ -53,10 +52,11 @@ class HttpRequester(Requester):
53
52
  """
54
53
 
55
54
  name: str
56
- url_base: Union[InterpolatedString, str]
57
55
  config: Config
58
56
  parameters: InitVar[Mapping[str, Any]]
59
57
 
58
+ url: Optional[Union[InterpolatedString, str]] = None
59
+ url_base: Optional[Union[InterpolatedString, str]] = None
60
60
  path: Optional[Union[InterpolatedString, str]] = None
61
61
  authenticator: Optional[DeclarativeAuthenticator] = None
62
62
  http_method: Union[str, HttpMethod] = HttpMethod.GET
@@ -71,7 +71,14 @@ class HttpRequester(Requester):
71
71
  decoder: Decoder = field(default_factory=lambda: JsonDecoder(parameters={}))
72
72
 
73
73
  def __post_init__(self, parameters: Mapping[str, Any]) -> None:
74
- self._url_base = InterpolatedString.create(self.url_base, parameters=parameters)
74
+ self._url = InterpolatedString.create(
75
+ self.url if self.url else EmptyString, parameters=parameters
76
+ )
77
+ # deprecated
78
+ self._url_base = InterpolatedString.create(
79
+ self.url_base if self.url_base else EmptyString, parameters=parameters
80
+ )
81
+ # deprecated
75
82
  self._path = InterpolatedString.create(
76
83
  self.path if self.path else EmptyString, parameters=parameters
77
84
  )
@@ -120,6 +127,51 @@ class HttpRequester(Requester):
120
127
  def get_authenticator(self) -> DeclarativeAuthenticator:
121
128
  return self._authenticator
122
129
 
130
+ def get_url(
131
+ self,
132
+ *,
133
+ stream_state: Optional[StreamState] = None,
134
+ stream_slice: Optional[StreamSlice] = None,
135
+ next_page_token: Optional[Mapping[str, Any]] = None,
136
+ ) -> str:
137
+ interpolation_context = get_interpolation_context(
138
+ stream_state=stream_state,
139
+ stream_slice=stream_slice,
140
+ next_page_token=next_page_token,
141
+ )
142
+
143
+ return str(self._url.eval(self.config, **interpolation_context))
144
+
145
+ def _get_url(
146
+ self,
147
+ *,
148
+ path: Optional[str] = None,
149
+ stream_state: Optional[StreamState] = None,
150
+ stream_slice: Optional[StreamSlice] = None,
151
+ next_page_token: Optional[Mapping[str, Any]] = None,
152
+ ) -> str:
153
+ url = self.get_url(
154
+ stream_state=stream_state,
155
+ stream_slice=stream_slice,
156
+ next_page_token=next_page_token,
157
+ )
158
+
159
+ url_base = self.get_url_base(
160
+ stream_state=stream_state,
161
+ stream_slice=stream_slice,
162
+ next_page_token=next_page_token,
163
+ )
164
+
165
+ path = path or self.get_path(
166
+ stream_state=stream_state,
167
+ stream_slice=stream_slice,
168
+ next_page_token=next_page_token,
169
+ )
170
+
171
+ full_url = self._join_url(url_base, path) if url_base else url + path if path else url
172
+
173
+ return full_url
174
+
123
175
  def get_url_base(
124
176
  self,
125
177
  *,
@@ -349,7 +401,7 @@ class HttpRequester(Requester):
349
401
  return options
350
402
 
351
403
  @classmethod
352
- def _join_url(cls, url_base: str, path: str) -> str:
404
+ def _join_url(cls, url_base: str, path: Optional[str] = None) -> str:
353
405
  """
354
406
  Joins a base URL with a given path and returns the resulting URL with any trailing slash removed.
355
407
 
@@ -358,7 +410,7 @@ class HttpRequester(Requester):
358
410
 
359
411
  Args:
360
412
  url_base (str): The base URL to which the path will be appended.
361
- path (str): The path to join with the base URL.
413
+ path (Optional[str]): The path to join with the base URL.
362
414
 
363
415
  Returns:
364
416
  str: The resulting joined URL.
@@ -399,18 +451,11 @@ class HttpRequester(Requester):
399
451
  ) -> Optional[requests.Response]:
400
452
  request, response = self._http_client.send_request(
401
453
  http_method=self.get_method().value,
402
- url=self._join_url(
403
- self.get_url_base(
404
- stream_state=stream_state,
405
- stream_slice=stream_slice,
406
- next_page_token=next_page_token,
407
- ),
408
- path
409
- or self.get_path(
410
- stream_state=stream_state,
411
- stream_slice=stream_slice,
412
- next_page_token=next_page_token,
413
- ),
454
+ url=self._get_url(
455
+ path=path,
456
+ stream_state=stream_state,
457
+ stream_slice=stream_slice,
458
+ next_page_token=next_page_token,
414
459
  ),
415
460
  request_kwargs={"stream": self.stream_response},
416
461
  headers=self._request_headers(
@@ -6,6 +6,9 @@ from dataclasses import InitVar, dataclass, field
6
6
  from typing import Any, List, Mapping, MutableMapping, Optional, Union
7
7
 
8
8
  from airbyte_cdk.sources.declarative.interpolation.interpolated_nested_mapping import NestedMapping
9
+ from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
10
+ RequestBody,
11
+ )
9
12
  from airbyte_cdk.sources.declarative.requesters.request_options.interpolated_nested_request_input_provider import (
10
13
  InterpolatedNestedRequestInputProvider,
11
14
  )
@@ -38,6 +41,7 @@ class InterpolatedRequestOptionsProvider(RequestOptionsProvider):
38
41
  config: Config = field(default_factory=dict)
39
42
  request_parameters: Optional[RequestInput] = None
40
43
  request_headers: Optional[RequestInput] = None
44
+ request_body: Optional[RequestBody] = None
41
45
  request_body_data: Optional[RequestInput] = None
42
46
  request_body_json: Optional[NestedMapping] = None
43
47
  query_properties_key: Optional[str] = None
@@ -47,16 +51,19 @@ class InterpolatedRequestOptionsProvider(RequestOptionsProvider):
47
51
  self.request_parameters = {}
48
52
  if self.request_headers is None:
49
53
  self.request_headers = {}
54
+ # resolve the request body to either data or json
55
+ self._resolve_request_body()
56
+ # If request_body is not provided, set request_body_data and request_body_json to empty dicts
50
57
  if self.request_body_data is None:
51
58
  self.request_body_data = {}
52
59
  if self.request_body_json is None:
53
60
  self.request_body_json = {}
54
-
61
+ # If both request_body_data and request_body_json are provided, raise an error
55
62
  if self.request_body_json and self.request_body_data:
56
63
  raise ValueError(
57
64
  "RequestOptionsProvider should only contain either 'request_body_data' or 'request_body_json' not both"
58
65
  )
59
-
66
+ # set interpolators
60
67
  self._parameter_interpolator = InterpolatedRequestInputProvider(
61
68
  config=self.config, request_inputs=self.request_parameters, parameters=parameters
62
69
  )
@@ -70,6 +77,21 @@ class InterpolatedRequestOptionsProvider(RequestOptionsProvider):
70
77
  config=self.config, request_inputs=self.request_body_json, parameters=parameters
71
78
  )
72
79
 
80
+ def _resolve_request_body(self) -> None:
81
+ """
82
+ Resolves the request body configuration by setting either `request_body_data` or `request_body_json`
83
+ based on the type specified in `self.request_body`. If neither is provided, both are initialized as empty
84
+ dictionaries. Raises a ValueError if both `request_body_data` and `request_body_json` are set simultaneously.
85
+ Raises:
86
+ ValueError: If both `request_body_data` and `request_body_json` are provided.
87
+ """
88
+ # Resolve the request body to either data or json
89
+ if self.request_body is not None and self.request_body.type is not None:
90
+ if self.request_body.type == "RequestBodyData":
91
+ self.request_body_data = self.request_body.value
92
+ elif self.request_body.type == "RequestBodyJson":
93
+ self.request_body_json = self.request_body.value
94
+
73
95
  def get_request_params(
74
96
  self,
75
97
  *,
@@ -34,6 +34,18 @@ class Requester(RequestOptionsProvider):
34
34
  """
35
35
  pass
36
36
 
37
+ @abstractmethod
38
+ def get_url(
39
+ self,
40
+ *,
41
+ stream_state: Optional[StreamState],
42
+ stream_slice: Optional[StreamSlice],
43
+ next_page_token: Optional[Mapping[str, Any]],
44
+ ) -> str:
45
+ """
46
+ :return: URL base for the API endpoint e.g: if you wanted to hit https://myapi.com/v1/some_entity then this should return "https://myapi.com/v1/"
47
+ """
48
+
37
49
  @abstractmethod
38
50
  def get_url_base(
39
51
  self,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: airbyte-cdk
3
- Version: 6.48.1
3
+ Version: 6.48.2
4
4
  Summary: A framework for writing Airbyte Connectors.
5
5
  Home-page: https://airbyte.com
6
6
  License: MIT
@@ -20,7 +20,7 @@ airbyte_cdk/connector_builder/models.py,sha256=9pIZ98LW_d6fRS39VdnUOf3cxGt4TkC5M
20
20
  airbyte_cdk/connector_builder/test_reader/__init__.py,sha256=iTwBMoI9vaJotEgpqZbFjlxRcbxXYypSVJ9YxeHk7wc,120
21
21
  airbyte_cdk/connector_builder/test_reader/helpers.py,sha256=Iczn-_iczS2CaIAunWwyFcX0uLTra8Wh9JVfzm1Gfxo,26765
22
22
  airbyte_cdk/connector_builder/test_reader/message_grouper.py,sha256=84BAEPIBHMq3WCfO14WNvh_q7OsjGgDt0q1FTu8eW-w,6918
23
- airbyte_cdk/connector_builder/test_reader/reader.py,sha256=wJtuYTZuc24-JlGF4UBFTJ2PChLjcQrvldqAWJM9Y9Y,20775
23
+ airbyte_cdk/connector_builder/test_reader/reader.py,sha256=mP1yHK5vG38KxoKoT2QQ7ZNbkdLA1rMAU3EKpucjHls,21098
24
24
  airbyte_cdk/connector_builder/test_reader/types.py,sha256=hPZG3jO03kBaPyW94NI3JHRS1jxXGSNBcN1HFzOxo5Y,2528
25
25
  airbyte_cdk/destinations/__init__.py,sha256=FyDp28PT_YceJD5HDFhA-mrGfX9AONIyMQ4d68CHNxQ,213
26
26
  airbyte_cdk/destinations/destination.py,sha256=CIq-yb8C_0QvcKCtmStaHfiqn53GEfRAIGGCkJhKP1Q,5880
@@ -45,7 +45,7 @@ airbyte_cdk/manifest_migrations/migrations/__init__.py,sha256=SJ7imfOgCRYOVaFkW2
45
45
  airbyte_cdk/manifest_migrations/migrations/http_requester_path_to_url.py,sha256=IIn2SjRh1v2yaSBFUCDyBHpX6mBhlckhvbsSg55mREI,2153
46
46
  airbyte_cdk/manifest_migrations/migrations/http_requester_request_body_json_data_to_request_body.py,sha256=70md8yDu8SWl2JkkFcEs8kyXUbP0F_obIzyHsygyR9k,1777
47
47
  airbyte_cdk/manifest_migrations/migrations/http_requester_url_base_to_url.py,sha256=EX1MVYVpoWypA28qoH48wA0SYZjGdlR8bcSixTDzfgo,1346
48
- airbyte_cdk/manifest_migrations/migrations/registry.yaml,sha256=56B09vbBlGWKF5KSB-3rashZLRiJmL8si_lmTokXWsc,960
48
+ airbyte_cdk/manifest_migrations/migrations/registry.yaml,sha256=pMG4JzHQyxvTjxhTZpzUXHb0BhwkY7w_6CtTwaUZ_K0,960
49
49
  airbyte_cdk/manifest_migrations/migrations_registry.py,sha256=zly2fwaOxDukqC7eowzrDlvhA2v71FjW74kDzvRXhSY,2619
50
50
  airbyte_cdk/models/__init__.py,sha256=Et9wJWs5VOWynGbb-3aJRhsdAHAiLkNNLxdwqJAuqkw,2114
51
51
  airbyte_cdk/models/airbyte_protocol.py,sha256=oZdKsZ7yPjUt9hvxdWNpxCtgjSV2RWhf4R9Np03sqyY,3613
@@ -89,8 +89,8 @@ airbyte_cdk/sources/declarative/concurrent_declarative_source.py,sha256=GoZJ8Oxb
89
89
  airbyte_cdk/sources/declarative/datetime/__init__.py,sha256=4Hw-PX1-VgESLF16cDdvuYCzGJtHntThLF4qIiULWeo,61
90
90
  airbyte_cdk/sources/declarative/datetime/datetime_parser.py,sha256=_zGNGq31RNy_0QBLt_EcTvgPyhj7urPdx6oA3M5-r3o,3150
91
91
  airbyte_cdk/sources/declarative/datetime/min_max_datetime.py,sha256=0BHBtDNQZfvwM45-tY5pNlTcKAFSGGNxemoi0Jic-0E,5785
92
- airbyte_cdk/sources/declarative/declarative_component_schema.yaml,sha256=I0jTe3nUqS5pW-LbdOQlYuHZIJC3nNAf_LV7XgmfA4g,162221
93
- airbyte_cdk/sources/declarative/declarative_source.py,sha256=nF7wBqFd3AQmEKAm4CnIo29CJoQL562cJGSCeL8U8bA,1531
92
+ airbyte_cdk/sources/declarative/declarative_component_schema.yaml,sha256=C_hjPvQHfNGNTt2rXp9nCl8T_tPZBoPx0D5yEBi6ZWg,165127
93
+ airbyte_cdk/sources/declarative/declarative_source.py,sha256=qmyMnnet92eGc3C22yBtpvD5UZjqdhsAafP_zxI5wp8,1814
94
94
  airbyte_cdk/sources/declarative/declarative_stream.py,sha256=dCRlddBUSaJmBNBz1pSO1r2rTw8AP5d2_vlmIeGs2gg,10767
95
95
  airbyte_cdk/sources/declarative/decoders/__init__.py,sha256=JHb_0d3SE6kNY10mxA5YBEKPeSbsWYjByq1gUQxepoE,953
96
96
  airbyte_cdk/sources/declarative/decoders/composite_raw_decoder.py,sha256=Jd7URkDQBoHSDQHQuYUqzeex1HYfLRtGcY_-dVW33pA,7884
@@ -122,24 +122,25 @@ airbyte_cdk/sources/declarative/interpolation/__init__.py,sha256=Kh7FxhfetyNVDnA
122
122
  airbyte_cdk/sources/declarative/interpolation/filters.py,sha256=cYap5zzOxIJWCLIfbkNlpyfUhjZ8FklLroIG4WGzYVs,5537
123
123
  airbyte_cdk/sources/declarative/interpolation/interpolated_boolean.py,sha256=8F3ntT_Mfo8cO9n6dCq8rTfJIpfKmzRCsVtVdhzaoGc,1964
124
124
  airbyte_cdk/sources/declarative/interpolation/interpolated_mapping.py,sha256=h36RIng4GZ9v4o_fRmgJjTNOtWmhK7NOILU1oSKPE4Q,2083
125
- airbyte_cdk/sources/declarative/interpolation/interpolated_nested_mapping.py,sha256=vjwvkLk7_l6YDcFClwjCMcTleRjQBh7-dzny7PUaoG8,1857
125
+ airbyte_cdk/sources/declarative/interpolation/interpolated_nested_mapping.py,sha256=myVaNtFqxOAwrbp93rgd1dhkqyuvXvET9rsimQ89ktc,1873
126
126
  airbyte_cdk/sources/declarative/interpolation/interpolated_string.py,sha256=CQkHqGlfa87G6VYMtBAQWin7ECKpfMdrDcg0JO5_rhc,3212
127
127
  airbyte_cdk/sources/declarative/interpolation/interpolation.py,sha256=9IoeuWam3L6GyN10L6U8xNWXmkt9cnahSDNkez1OmFY,982
128
128
  airbyte_cdk/sources/declarative/interpolation/jinja.py,sha256=UQeuS4Vpyp4hlOn-R3tRyeBX0e9IoV6jQ6gH-Jz8lY0,7182
129
129
  airbyte_cdk/sources/declarative/interpolation/macros.py,sha256=UYSJ5gW7TkHALYnNvUnRP3RlyGwGuRMObF3BHuNzjJM,5320
130
- airbyte_cdk/sources/declarative/manifest_declarative_source.py,sha256=yPQ4Qsxt8rzgbj52TLVFJiSRJp4lbFF-H7dSsr88E58,22961
130
+ airbyte_cdk/sources/declarative/manifest_declarative_source.py,sha256=cZNUOeIogrCmCS7RXeJqQIlnsANigz1cngpLko02M2g,23191
131
131
  airbyte_cdk/sources/declarative/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
132
132
  airbyte_cdk/sources/declarative/migrations/legacy_to_per_partition_state_migration.py,sha256=iemy3fKLczcU0-Aor7tx5jcT6DRedKMqyK7kCOp01hg,3924
133
133
  airbyte_cdk/sources/declarative/migrations/state_migration.py,sha256=KWPjealMLKSMtajXgkdGgKg7EmTLR-CqqD7UIh0-eDU,794
134
134
  airbyte_cdk/sources/declarative/models/__init__.py,sha256=nUFxNCiKeYRVXuZEKA7GD-lTHxsiKcQ8FitZjKhPIvE,100
135
- airbyte_cdk/sources/declarative/models/declarative_component_schema.py,sha256=i38088qAfh5YMIOEkHdOVqMwDDCayAYtj66EHb3eJNE,114915
135
+ airbyte_cdk/sources/declarative/models/base_model_with_deprecations.py,sha256=Rq5kzR5bflqBf6td2ZAgw6lP3iN_mNi4tjntn_R01_o,5851
136
+ airbyte_cdk/sources/declarative/models/declarative_component_schema.py,sha256=Vf8LSt-leRKOpxQVQsGxWpG2aq9s9yvZKi4DYbpmf0s,117147
136
137
  airbyte_cdk/sources/declarative/parsers/__init__.py,sha256=ZnqYNxHsKCgO38IwB34RQyRMXTs4GTvlRi3ImKnIioo,61
137
138
  airbyte_cdk/sources/declarative/parsers/custom_code_compiler.py,sha256=nlVvHC511NUyDEEIRBkoeDTAvLqKNp-hRy8D19z8tdk,5941
138
139
  airbyte_cdk/sources/declarative/parsers/custom_exceptions.py,sha256=wnRUP0Xeru9Rbu5OexXSDN9QWDo8YU4tT9M2LDVOgGA,802
139
140
  airbyte_cdk/sources/declarative/parsers/manifest_component_transformer.py,sha256=RUyFZS0zslLb7UfQrvqMC--k5CVLNSp7zHw6kbosvKE,9688
140
141
  airbyte_cdk/sources/declarative/parsers/manifest_normalizer.py,sha256=laBy7ebjA-PiNwc-50U4FHvMqS_mmHvnabxgFs4CjGw,17069
141
142
  airbyte_cdk/sources/declarative/parsers/manifest_reference_resolver.py,sha256=pJmg78vqE5VfUrF_KJnWjucQ4k9IWFULeAxHCowrHXE,6806
142
- airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py,sha256=YXR_cKEL6U-B6eji-FxvHFw_6V-bBAVmC4-M5IawXtQ,163774
143
+ airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py,sha256=YZ7WtSFKZ-0HfBq6l-OvmLGkcKcPSg-9wwYMRGYBU0g,166254
143
144
  airbyte_cdk/sources/declarative/partition_routers/__init__.py,sha256=TBC9AkGaUqHm2IKHMPN6punBIcY5tWGULowcLoAVkfw,1109
144
145
  airbyte_cdk/sources/declarative/partition_routers/async_job_partition_router.py,sha256=VelO7zKqKtzMJ35jyFeg0ypJLQC0plqqIBNXoBW1G2E,3001
145
146
  airbyte_cdk/sources/declarative/partition_routers/cartesian_product_stream_slicer.py,sha256=c5cuVFM6NFkuQqG8Z5IwkBuwDrvXZN1CunUOM_L0ezg,6892
@@ -164,7 +165,7 @@ airbyte_cdk/sources/declarative/requesters/error_handlers/default_http_response_
164
165
  airbyte_cdk/sources/declarative/requesters/error_handlers/error_handler.py,sha256=Tan66odx8VHzfdyyXMQkXz2pJYksllGqvxmpoajgcK4,669
165
166
  airbyte_cdk/sources/declarative/requesters/error_handlers/http_response_filter.py,sha256=E-fQbt4ShfxZVoqfnmOx69C6FUPWZz8BIqI3DN9Kcjs,7935
166
167
  airbyte_cdk/sources/declarative/requesters/http_job_repository.py,sha256=uDyLvNsJ183oh3TT-O1PDOgpGt7OD1uqpLTDWTyb9PA,14271
167
- airbyte_cdk/sources/declarative/requesters/http_requester.py,sha256=uEhUmLGVuwfadKz0c1vunrr66ZNYWmotKZWiaPYPDzw,17402
168
+ airbyte_cdk/sources/declarative/requesters/http_requester.py,sha256=1qUqNxJ6I_4uSkW4KYXEtygVioURIEmiaDU8GMl_Jcs,18833
168
169
  airbyte_cdk/sources/declarative/requesters/paginators/__init__.py,sha256=uArbKs9JKNCt7t9tZoeWwjDpyI1HoPp29FNW0JzvaEM,644
169
170
  airbyte_cdk/sources/declarative/requesters/paginators/default_paginator.py,sha256=SB-Af3CRb4mJwhm4EKNxzl_PK2w5QS4tqrSNNMO2IV4,12760
170
171
  airbyte_cdk/sources/declarative/requesters/paginators/no_pagination.py,sha256=b1-zKxYOUMHn7ahdWpzKEzfG4A7s_WQWy-vzRqZWzME,2152
@@ -188,10 +189,10 @@ airbyte_cdk/sources/declarative/requesters/request_options/datetime_based_reques
188
189
  airbyte_cdk/sources/declarative/requesters/request_options/default_request_options_provider.py,sha256=SRROdPJZ5kuqHLOlkh115pWP9nDGfDxRYPgH9oD3hPo,1798
189
190
  airbyte_cdk/sources/declarative/requesters/request_options/interpolated_nested_request_input_provider.py,sha256=86YozYuBDfu0t9NbevIvQoGU0vqTP4rt3dRSTsHz3PA,2269
190
191
  airbyte_cdk/sources/declarative/requesters/request_options/interpolated_request_input_provider.py,sha256=rR00kE64U2yL0McU1gPr4_W5_sLUqwDgL3Nvj691nRU,2884
191
- airbyte_cdk/sources/declarative/requesters/request_options/interpolated_request_options_provider.py,sha256=dRlG1IyEOVzWFw7wm-8TBPn7JUtZw3jz6oAoH5yuuf0,6375
192
+ airbyte_cdk/sources/declarative/requesters/request_options/interpolated_request_options_provider.py,sha256=TKerU1oGJJRGPk9_AXpKnaQVdNNIYpdLG1lK3HfaHS8,7741
192
193
  airbyte_cdk/sources/declarative/requesters/request_options/request_options_provider.py,sha256=8YRiDzjYvqJ-aMmKFcjqzv_-e8OZ5QG_TbpZ-nuCu6s,2590
193
194
  airbyte_cdk/sources/declarative/requesters/request_path.py,sha256=S3MeFvcaQrMbOkSY2W2VbXLNomqt_3eXqVd9ZhgNwUs,299
194
- airbyte_cdk/sources/declarative/requesters/requester.py,sha256=OcDzuCBgD1owK_lBPG0KbRRHRn9kzbuRveU4HejDiv4,5116
195
+ airbyte_cdk/sources/declarative/requesters/requester.py,sha256=T6tMx_Bx4iT-0YVjY7IzgRil-gaIu9n01b1iwpTh3Ek,5516
195
196
  airbyte_cdk/sources/declarative/resolvers/__init__.py,sha256=NiDcz5qi8HPsfX94MUmnX0Rgs_kQXGvucOmJjNWlxKQ,1207
196
197
  airbyte_cdk/sources/declarative/resolvers/components_resolver.py,sha256=KPjKc0yb9artL4ZkeqN8RmEykHH6FJgqXD7fCEnh1X0,1936
197
198
  airbyte_cdk/sources/declarative/resolvers/config_components_resolver.py,sha256=dz4iJV9liD_LzY_Mn4XmAStoUll60R3MIGWV4aN3pgg,5223
@@ -407,9 +408,9 @@ airbyte_cdk/utils/slice_hasher.py,sha256=EDxgROHDbfG-QKQb59m7h_7crN1tRiawdf5uU7G
407
408
  airbyte_cdk/utils/spec_schema_transformations.py,sha256=-5HTuNsnDBAhj-oLeQXwpTGA0HdcjFOf2zTEMUTTg_Y,816
408
409
  airbyte_cdk/utils/stream_status_utils.py,sha256=ZmBoiy5HVbUEHAMrUONxZvxnvfV9CesmQJLDTAIWnWw,1171
409
410
  airbyte_cdk/utils/traced_exception.py,sha256=C8uIBuCL_E4WnBAOPSxBicD06JAldoN9fGsQDp463OY,6292
410
- airbyte_cdk-6.48.1.dist-info/LICENSE.txt,sha256=Wfe61S4BaGPj404v8lrAbvhjYR68SHlkzeYrg3_bbuM,1051
411
- airbyte_cdk-6.48.1.dist-info/LICENSE_SHORT,sha256=aqF6D1NcESmpn-cqsxBtszTEnHKnlsp8L4x9wAh3Nxg,55
412
- airbyte_cdk-6.48.1.dist-info/METADATA,sha256=scl_OXlgL349P2PgmdntFjkKVIBv9d_dPTIF7S2iKmA,6323
413
- airbyte_cdk-6.48.1.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
414
- airbyte_cdk-6.48.1.dist-info/entry_points.txt,sha256=AKWbEkHfpzzk9nF9tqBUaw1MbvTM4mGtEzmZQm0ZWvM,139
415
- airbyte_cdk-6.48.1.dist-info/RECORD,,
411
+ airbyte_cdk-6.48.2.dist-info/LICENSE.txt,sha256=Wfe61S4BaGPj404v8lrAbvhjYR68SHlkzeYrg3_bbuM,1051
412
+ airbyte_cdk-6.48.2.dist-info/LICENSE_SHORT,sha256=aqF6D1NcESmpn-cqsxBtszTEnHKnlsp8L4x9wAh3Nxg,55
413
+ airbyte_cdk-6.48.2.dist-info/METADATA,sha256=0SCcRtnWh4AI7620nilMQ_4gxFiiTljCCpb5AB6B_R4,6323
414
+ airbyte_cdk-6.48.2.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
415
+ airbyte_cdk-6.48.2.dist-info/entry_points.txt,sha256=AKWbEkHfpzzk9nF9tqBUaw1MbvTM4mGtEzmZQm0ZWvM,139
416
+ airbyte_cdk-6.48.2.dist-info/RECORD,,