airbyte-cdk 6.48.6__py3-none-any.whl → 6.48.7.dev0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -18,6 +18,7 @@ from airbyte_cdk.models import (
18
18
  AirbyteMessageSerializer,
19
19
  ConfiguredAirbyteCatalog,
20
20
  ConfiguredAirbyteCatalogSerializer,
21
+ DestinationCatalog,
21
22
  Type,
22
23
  )
23
24
  from airbyte_cdk.sources.utils.schema_helpers import check_config_against_spec_or_exit
@@ -26,8 +27,74 @@ from airbyte_cdk.utils.traced_exception import AirbyteTracedException
26
27
  logger = logging.getLogger("airbyte")
27
28
 
28
29
 
30
+ def parse_args(args: List[str]) -> argparse.Namespace:
31
+ """
32
+ :param args: commandline arguments
33
+ :return:
34
+ """
35
+
36
+ parent_parser = argparse.ArgumentParser(add_help=False)
37
+ parent_parser.add_argument(
38
+ "--debug", action="store_true", help="enables detailed debug logs related to the sync"
39
+ )
40
+ main_parser = argparse.ArgumentParser()
41
+ subparsers = main_parser.add_subparsers(title="commands", dest="command")
42
+
43
+ # spec
44
+ subparsers.add_parser(
45
+ "spec", help="outputs the json configuration specification", parents=[parent_parser]
46
+ )
47
+
48
+ # check
49
+ check_parser = subparsers.add_parser(
50
+ "check", help="checks the config can be used to connect", parents=[parent_parser]
51
+ )
52
+ required_check_parser = check_parser.add_argument_group("required named arguments")
53
+ required_check_parser.add_argument(
54
+ "--config", type=str, required=True, help="path to the json configuration file"
55
+ )
56
+
57
+ # discover
58
+ discover_parser = subparsers.add_parser(
59
+ "discover",
60
+ help="discover the objects available in the destination",
61
+ parents=[parent_parser],
62
+ )
63
+ required_discover_parser = discover_parser.add_argument_group("required named arguments")
64
+ required_discover_parser.add_argument(
65
+ "--config", type=str, required=True, help="path to the json configuration file"
66
+ )
67
+
68
+ # write
69
+ write_parser = subparsers.add_parser(
70
+ "write", help="Writes data to the destination", parents=[parent_parser]
71
+ )
72
+ write_required = write_parser.add_argument_group("required named arguments")
73
+ write_required.add_argument(
74
+ "--config", type=str, required=True, help="path to the JSON configuration file"
75
+ )
76
+ write_required.add_argument(
77
+ "--catalog", type=str, required=True, help="path to the configured catalog JSON file"
78
+ )
79
+
80
+ parsed_args = main_parser.parse_args(args)
81
+ cmd = parsed_args.command
82
+ if not cmd:
83
+ raise Exception("No command entered. ")
84
+ elif cmd not in ["spec", "check", "discover", "write"]:
85
+ # This is technically dead code since parse_args() would fail if this was the case
86
+ # But it's non-obvious enough to warrant placing it here anyways
87
+ raise Exception(f"Unknown command entered: {cmd}")
88
+
89
+ return parsed_args
90
+
91
+
29
92
  class Destination(Connector, ABC):
30
- VALID_CMDS = {"spec", "check", "write"}
93
+ VALID_CMDS = {"spec", "check", "discover", "write"}
94
+
95
+ def discover(self) -> DestinationCatalog:
96
+ """Implement to define what objects are available in the destination"""
97
+ raise NotImplementedError("Discover method is not implemented")
31
98
 
32
99
  @abstractmethod
33
100
  def write(
@@ -68,52 +135,9 @@ class Destination(Connector, ABC):
68
135
  )
69
136
  logger.info("Writing complete.")
70
137
 
71
- def parse_args(self, args: List[str]) -> argparse.Namespace:
72
- """
73
- :param args: commandline arguments
74
- :return:
75
- """
76
-
77
- parent_parser = argparse.ArgumentParser(add_help=False)
78
- main_parser = argparse.ArgumentParser()
79
- subparsers = main_parser.add_subparsers(title="commands", dest="command")
80
-
81
- # spec
82
- subparsers.add_parser(
83
- "spec", help="outputs the json configuration specification", parents=[parent_parser]
84
- )
85
-
86
- # check
87
- check_parser = subparsers.add_parser(
88
- "check", help="checks the config can be used to connect", parents=[parent_parser]
89
- )
90
- required_check_parser = check_parser.add_argument_group("required named arguments")
91
- required_check_parser.add_argument(
92
- "--config", type=str, required=True, help="path to the json configuration file"
93
- )
94
-
95
- # write
96
- write_parser = subparsers.add_parser(
97
- "write", help="Writes data to the destination", parents=[parent_parser]
98
- )
99
- write_required = write_parser.add_argument_group("required named arguments")
100
- write_required.add_argument(
101
- "--config", type=str, required=True, help="path to the JSON configuration file"
102
- )
103
- write_required.add_argument(
104
- "--catalog", type=str, required=True, help="path to the configured catalog JSON file"
105
- )
106
-
107
- parsed_args = main_parser.parse_args(args)
108
- cmd = parsed_args.command
109
- if not cmd:
110
- raise Exception("No command entered. ")
111
- elif cmd not in ["spec", "check", "write"]:
112
- # This is technically dead code since parse_args() would fail if this was the case
113
- # But it's non-obvious enough to warrant placing it here anyways
114
- raise Exception(f"Unknown command entered: {cmd}")
115
-
116
- return parsed_args
138
+ @staticmethod
139
+ def parse_args(args: List[str]) -> argparse.Namespace:
140
+ return parse_args(args)
117
141
 
118
142
  def run_cmd(self, parsed_args: argparse.Namespace) -> Iterable[AirbyteMessage]:
119
143
  cmd = parsed_args.command
@@ -137,6 +161,8 @@ class Destination(Connector, ABC):
137
161
 
138
162
  if cmd == "check":
139
163
  yield self._run_check(config=config)
164
+ elif cmd == "discover":
165
+ yield AirbyteMessage(type=Type.DESTINATION_CATALOG, destination_catalog=self.discover())
140
166
  elif cmd == "write":
141
167
  # Wrap in UTF-8 to override any other input encodings
142
168
  wrapped_stdin = io.TextIOWrapper(sys.stdin.buffer, encoding="utf-8")
@@ -35,6 +35,10 @@ from .airbyte_protocol import (
35
35
  ConfiguredAirbyteCatalog,
36
36
  ConfiguredAirbyteStream,
37
37
  ConnectorSpecification,
38
+ DestinationCatalog,
39
+ DestinationObject,
40
+ DestinationObjectProperty,
41
+ DestinationOperation,
38
42
  DestinationSyncMode,
39
43
  EstimateType,
40
44
  FailureType,
@@ -299,8 +299,8 @@ definitions:
299
299
  - "$ref": "#/definitions/CustomAuthenticator"
300
300
  - "$ref": "#/definitions/OAuthAuthenticator"
301
301
  - "$ref": "#/definitions/JwtAuthenticator"
302
- - "$ref": "#/definitions/NoAuth"
303
302
  - "$ref": "#/definitions/SessionTokenAuthenticator"
303
+ - "$ref": "#/definitions/NoAuth"
304
304
  - "$ref": "#/definitions/LegacySessionTokenAuthenticator"
305
305
  examples:
306
306
  - authenticators:
@@ -1417,7 +1417,6 @@ definitions:
1417
1417
  - "$ref": "#/definitions/CustomIncrementalSync"
1418
1418
  primary_key:
1419
1419
  title: Primary Key
1420
- description: The primary key of the stream.
1421
1420
  "$ref": "#/definitions/PrimaryKey"
1422
1421
  default: ""
1423
1422
  schema_loader:
@@ -1468,18 +1467,18 @@ definitions:
1468
1467
  requester:
1469
1468
  description: Requester component that describes how to prepare HTTP requests to send to the source API.
1470
1469
  anyOf:
1471
- - "$ref": "#/definitions/CustomRequester"
1472
1470
  - "$ref": "#/definitions/HttpRequester"
1471
+ - "$ref": "#/definitions/CustomRequester"
1473
1472
  download_target_extractor:
1474
1473
  description: Responsible for fetching the url where the file is located. This is applied on each records and not on the HTTP response
1475
1474
  anyOf:
1476
- - "$ref": "#/definitions/CustomRecordExtractor"
1477
1475
  - "$ref": "#/definitions/DpathExtractor"
1476
+ - "$ref": "#/definitions/CustomRecordExtractor"
1478
1477
  file_extractor:
1479
1478
  description: Responsible for fetching the content of the file. If not defined, the assumption is that the whole response body is the file content
1480
1479
  anyOf:
1481
- - "$ref": "#/definitions/CustomRecordExtractor"
1482
1480
  - "$ref": "#/definitions/DpathExtractor"
1481
+ - "$ref": "#/definitions/CustomRecordExtractor"
1483
1482
  filename_extractor:
1484
1483
  description: Defines the name to store the file. Stream name is automatically added to the file path. File unique ID can be used to avoid overwriting files. Random UUID will be used if the extractor is not provided.
1485
1484
  type: string
@@ -1919,7 +1918,7 @@ definitions:
1919
1918
  deprecated: true
1920
1919
  deprecation_message: "Use `url` field instead."
1921
1920
  title: API Base URL
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.
1921
+ 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 Authenticator component for this.
1923
1922
  linkable: true
1924
1923
  type: string
1925
1924
  interpolation_context:
@@ -1937,8 +1936,8 @@ definitions:
1937
1936
  - "https://connect.squareup.com/v2/quotes/{{ stream_partition['id'] }}/quote_line_groups"
1938
1937
  - "https://example.com/api/v1/resource/{{ next_page_token['id'] }}"
1939
1938
  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.
1939
+ title: API Endpoint URL
1940
+ description: The URL of the source API endpoint. Do not put sensitive information (e.g. API tokens) into this field - Use the Authenticator component for this.
1942
1941
  type: string
1943
1942
  interpolation_context:
1944
1943
  - config
@@ -1958,7 +1957,7 @@ definitions:
1958
1957
  deprecated: true
1959
1958
  deprecation_message: "Use `url` field instead."
1960
1959
  title: URL Path
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.
1960
+ 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 Authenticator component for this.
1962
1961
  type: string
1963
1962
  interpolation_context:
1964
1963
  - config
@@ -1989,7 +1988,6 @@ definitions:
1989
1988
  linkable: true
1990
1989
  description: Authentication method to use for requests sent to the API.
1991
1990
  anyOf:
1992
- - "$ref": "#/definitions/NoAuth"
1993
1991
  - "$ref": "#/definitions/ApiKeyAuthenticator"
1994
1992
  - "$ref": "#/definitions/BasicHttpAuthenticator"
1995
1993
  - "$ref": "#/definitions/BearerAuthenticator"
@@ -1998,11 +1996,52 @@ definitions:
1998
1996
  - "$ref": "#/definitions/SessionTokenAuthenticator"
1999
1997
  - "$ref": "#/definitions/SelectiveAuthenticator"
2000
1998
  - "$ref": "#/definitions/CustomAuthenticator"
1999
+ - "$ref": "#/definitions/NoAuth"
2001
2000
  - "$ref": "#/definitions/LegacySessionTokenAuthenticator"
2002
2001
  fetch_properties_from_endpoint:
2003
2002
  title: Fetch Properties from Endpoint
2004
2003
  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.
2005
2004
  "$ref": "#/definitions/PropertiesFromEndpoint"
2005
+ request_parameters:
2006
+ title: Query Parameters
2007
+ description: Specifies the query parameters that should be set on an outgoing HTTP request given the inputs.
2008
+ anyOf:
2009
+ - type: object
2010
+ title: Key/Value Pairs
2011
+ additionalProperties:
2012
+ anyOf:
2013
+ - type: string
2014
+ - $ref: "#/definitions/QueryProperties"
2015
+ - type: string
2016
+ title: Interpolated Value
2017
+ interpolation_context:
2018
+ - next_page_token
2019
+ - stream_interval
2020
+ - stream_partition
2021
+ - stream_slice
2022
+ examples:
2023
+ - unit: "day"
2024
+ - query: 'last_event_time BETWEEN TIMESTAMP "{{ stream_interval.start_time }}" AND TIMESTAMP "{{ stream_interval.end_time }}"'
2025
+ - searchIn: "{{ ','.join(config.get('search_in', [])) }}"
2026
+ - sort_by[asc]: updated_at
2027
+ request_headers:
2028
+ title: Request Headers
2029
+ description: Return any non-auth headers. Authentication headers will overwrite any overlapping headers returned from this method.
2030
+ anyOf:
2031
+ - type: object
2032
+ title: Key/Value Pairs
2033
+ additionalProperties:
2034
+ type: string
2035
+ - type: string
2036
+ title: Interpolated Value
2037
+ interpolation_context:
2038
+ - next_page_token
2039
+ - stream_interval
2040
+ - stream_partition
2041
+ - stream_slice
2042
+ examples:
2043
+ - Output-Format: JSON
2044
+ - Version: "{{ config['version'] }}"
2006
2045
  request_body_data:
2007
2046
  deprecated: true
2008
2047
  deprecation_message: "Use `request_body` field instead."
@@ -2045,7 +2084,7 @@ definitions:
2045
2084
  field: "updated_at"
2046
2085
  order: "ascending"
2047
2086
  request_body:
2048
- title: Request Body Payload to be send as a part of the API request.
2087
+ title: Request Body
2049
2088
  description: Specifies how to populate the body of the request with a payload. Can contain nested objects.
2050
2089
  anyOf:
2051
2090
  - "$ref": "#/definitions/RequestBodyPlainText"
@@ -2081,46 +2120,6 @@ definitions:
2081
2120
  query:
2082
2121
  param1: "value1"
2083
2122
  param2: "{{ config['param2_value'] }}"
2084
- request_headers:
2085
- title: Request Headers
2086
- description: Return any non-auth headers. Authentication headers will overwrite any overlapping headers returned from this method.
2087
- anyOf:
2088
- - type: object
2089
- title: Key/Value Pairs
2090
- additionalProperties:
2091
- type: string
2092
- - type: string
2093
- title: Interpolated Value
2094
- interpolation_context:
2095
- - next_page_token
2096
- - stream_interval
2097
- - stream_partition
2098
- - stream_slice
2099
- examples:
2100
- - Output-Format: JSON
2101
- - Version: "{{ config['version'] }}"
2102
- request_parameters:
2103
- title: Query Parameters
2104
- description: Specifies the query parameters that should be set on an outgoing HTTP request given the inputs.
2105
- anyOf:
2106
- - type: object
2107
- title: Key/Value Pairs
2108
- additionalProperties:
2109
- anyOf:
2110
- - type: string
2111
- - $ref: "#/definitions/QueryProperties"
2112
- - type: string
2113
- title: Interpolated Value
2114
- interpolation_context:
2115
- - next_page_token
2116
- - stream_interval
2117
- - stream_partition
2118
- - stream_slice
2119
- examples:
2120
- - unit: "day"
2121
- - query: 'last_event_time BETWEEN TIMESTAMP "{{ stream_interval.start_time }}" AND TIMESTAMP "{{ stream_interval.end_time }}"'
2122
- - searchIn: "{{ ','.join(config.get('search_in', [])) }}"
2123
- - sort_by[asc]: updated_at
2124
2123
  error_handler:
2125
2124
  title: Error Handler
2126
2125
  description: Error handler component that defines how to handle errors.
@@ -3100,7 +3099,7 @@ definitions:
3100
3099
  type: array
3101
3100
  default: []
3102
3101
  items:
3103
- - type: string
3102
+ type: string
3104
3103
  interpolation_context:
3105
3104
  - config
3106
3105
  parent_key:
@@ -3155,14 +3154,19 @@ definitions:
3155
3154
  anyOf:
3156
3155
  - type: string
3157
3156
  title: Single Key
3157
+ description: The single top-level field to use as the primary key.
3158
3158
  - type: array
3159
3159
  title: Composite Key
3160
+ description: An array of top-level fields representing a composite primary key.
3160
3161
  items:
3161
3162
  type: string
3162
3163
  - type: array
3163
3164
  title: Composite Key of Nested Fields
3165
+ description: An array of arrays representing a composite primary key where the fields are nested fields.
3164
3166
  items:
3165
3167
  type: array
3168
+ title: Nested Field Path
3169
+ description: Path to the nested field in the record.
3166
3170
  items:
3167
3171
  type: string
3168
3172
  default: ""
@@ -3194,8 +3198,8 @@ definitions:
3194
3198
  retriever:
3195
3199
  description: Requester component that describes how to fetch the properties to query from a remote API endpoint.
3196
3200
  anyOf:
3197
- - "$ref": "#/definitions/CustomRetriever"
3198
3201
  - "$ref": "#/definitions/SimpleRetriever"
3202
+ - "$ref": "#/definitions/CustomRetriever"
3199
3203
  $parameters:
3200
3204
  type: object
3201
3205
  additionalProperties: true
@@ -3426,6 +3430,7 @@ definitions:
3426
3430
  additionalProperties: true
3427
3431
  LegacySessionTokenAuthenticator:
3428
3432
  title: Session Token Authenticator
3433
+ deprecated: true
3429
3434
  description: Deprecated - use SessionTokenAuthenticator instead. Authenticator for requests authenticated using session tokens. A session token is a random value generated by a server to identify a specific user for the duration of one interaction session.
3430
3435
  type: object
3431
3436
  required:
@@ -3534,15 +3539,15 @@ definitions:
3534
3539
  - "$ref": "#/definitions/HttpRequester"
3535
3540
  - "$ref": "#/definitions/CustomRequester"
3536
3541
  decoder:
3537
- title: Decoder
3542
+ title: HTTP Response Format
3538
3543
  description: Component decoding the response so records can be extracted.
3539
3544
  anyOf:
3540
- - "$ref": "#/definitions/CsvDecoder"
3541
- - "$ref": "#/definitions/GzipDecoder"
3542
3545
  - "$ref": "#/definitions/JsonDecoder"
3546
+ - "$ref": "#/definitions/XmlDecoder"
3547
+ - "$ref": "#/definitions/CsvDecoder"
3543
3548
  - "$ref": "#/definitions/JsonlDecoder"
3549
+ - "$ref": "#/definitions/GzipDecoder"
3544
3550
  - "$ref": "#/definitions/IterableDecoder"
3545
- - "$ref": "#/definitions/XmlDecoder"
3546
3551
  - "$ref": "#/definitions/ZipfileDecoder"
3547
3552
  - "$ref": "#/definitions/CustomDecoder"
3548
3553
  record_selector:
@@ -2080,8 +2080,8 @@ class SelectiveAuthenticator(BaseModel):
2080
2080
  CustomAuthenticator,
2081
2081
  OAuthAuthenticator,
2082
2082
  JwtAuthenticator,
2083
- NoAuth,
2084
2083
  SessionTokenAuthenticator,
2084
+ NoAuth,
2085
2085
  LegacySessionTokenAuthenticator,
2086
2086
  ],
2087
2087
  ] = Field(
@@ -2103,15 +2103,15 @@ class SelectiveAuthenticator(BaseModel):
2103
2103
 
2104
2104
  class FileUploader(BaseModel):
2105
2105
  type: Literal["FileUploader"]
2106
- requester: Union[CustomRequester, HttpRequester] = Field(
2106
+ requester: Union[HttpRequester, CustomRequester] = Field(
2107
2107
  ...,
2108
2108
  description="Requester component that describes how to prepare HTTP requests to send to the source API.",
2109
2109
  )
2110
- download_target_extractor: Union[CustomRecordExtractor, DpathExtractor] = Field(
2110
+ download_target_extractor: Union[DpathExtractor, CustomRecordExtractor] = Field(
2111
2111
  ...,
2112
2112
  description="Responsible for fetching the url where the file is located. This is applied on each records and not on the HTTP response",
2113
2113
  )
2114
- file_extractor: Optional[Union[CustomRecordExtractor, DpathExtractor]] = Field(
2114
+ file_extractor: Optional[Union[DpathExtractor, CustomRecordExtractor]] = Field(
2115
2115
  None,
2116
2116
  description="Responsible for fetching the content of the file. If not defined, the assumption is that the whole response body is the file content",
2117
2117
  )
@@ -2144,9 +2144,7 @@ class DeclarativeStream(BaseModel):
2144
2144
  description="Component used to fetch data incrementally based on a time field in the data.",
2145
2145
  title="Incremental Sync",
2146
2146
  )
2147
- primary_key: Optional[PrimaryKey] = Field(
2148
- "", description="The primary key of the stream.", title="Primary Key"
2149
- )
2147
+ primary_key: Optional[PrimaryKey] = Field("", title="Primary Key")
2150
2148
  schema_loader: Optional[
2151
2149
  Union[
2152
2150
  InlineSchemaLoader,
@@ -2242,7 +2240,7 @@ class HttpRequester(BaseModelWithDeprecations):
2242
2240
  None,
2243
2241
  deprecated=True,
2244
2242
  deprecation_message="Use `url` field instead.",
2245
- 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.",
2243
+ 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 Authenticator component for this.",
2246
2244
  examples=[
2247
2245
  "https://connect.squareup.com/v2",
2248
2246
  "{{ config['base_url'] or 'https://app.posthog.com'}}/api",
@@ -2253,20 +2251,20 @@ class HttpRequester(BaseModelWithDeprecations):
2253
2251
  )
2254
2252
  url: Optional[str] = Field(
2255
2253
  None,
2256
- 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.",
2254
+ description="The URL of the source API endpoint. Do not put sensitive information (e.g. API tokens) into this field - Use the Authenticator component for this.",
2257
2255
  examples=[
2258
2256
  "https://connect.squareup.com/v2",
2259
2257
  "{{ config['url'] or 'https://app.posthog.com'}}/api",
2260
2258
  "https://connect.squareup.com/v2/quotes/{{ stream_partition['id'] }}/quote_line_groups",
2261
2259
  "https://example.com/api/v1/resource/{{ next_page_token['id'] }}",
2262
2260
  ],
2263
- title="The URL of an API endpoint",
2261
+ title="API Endpoint URL",
2264
2262
  )
2265
2263
  path: Optional[str] = Field(
2266
2264
  None,
2267
2265
  deprecated=True,
2268
2266
  deprecation_message="Use `url` field instead.",
2269
- 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.",
2267
+ 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 Authenticator component for this.",
2270
2268
  examples=[
2271
2269
  "/products",
2272
2270
  "/quotes/{{ stream_partition['id'] }}/quote_line_groups",
@@ -2282,7 +2280,6 @@ class HttpRequester(BaseModelWithDeprecations):
2282
2280
  )
2283
2281
  authenticator: Optional[
2284
2282
  Union[
2285
- NoAuth,
2286
2283
  ApiKeyAuthenticator,
2287
2284
  BasicHttpAuthenticator,
2288
2285
  BearerAuthenticator,
@@ -2291,6 +2288,7 @@ class HttpRequester(BaseModelWithDeprecations):
2291
2288
  SessionTokenAuthenticator,
2292
2289
  SelectiveAuthenticator,
2293
2290
  CustomAuthenticator,
2291
+ NoAuth,
2294
2292
  LegacySessionTokenAuthenticator,
2295
2293
  ]
2296
2294
  ] = Field(
@@ -2303,6 +2301,25 @@ class HttpRequester(BaseModelWithDeprecations):
2303
2301
  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.",
2304
2302
  title="Fetch Properties from Endpoint",
2305
2303
  )
2304
+ request_parameters: Optional[Union[Dict[str, Union[str, QueryProperties]], str]] = Field(
2305
+ None,
2306
+ description="Specifies the query parameters that should be set on an outgoing HTTP request given the inputs.",
2307
+ examples=[
2308
+ {"unit": "day"},
2309
+ {
2310
+ "query": 'last_event_time BETWEEN TIMESTAMP "{{ stream_interval.start_time }}" AND TIMESTAMP "{{ stream_interval.end_time }}"'
2311
+ },
2312
+ {"searchIn": "{{ ','.join(config.get('search_in', [])) }}"},
2313
+ {"sort_by[asc]": "updated_at"},
2314
+ ],
2315
+ title="Query Parameters",
2316
+ )
2317
+ request_headers: Optional[Union[Dict[str, str], str]] = Field(
2318
+ None,
2319
+ description="Return any non-auth headers. Authentication headers will overwrite any overlapping headers returned from this method.",
2320
+ examples=[{"Output-Format": "JSON"}, {"Version": "{{ config['version'] }}"}],
2321
+ title="Request Headers",
2322
+ )
2306
2323
  request_body_data: Optional[Union[Dict[str, str], str]] = Field(
2307
2324
  None,
2308
2325
  deprecated=True,
@@ -2363,26 +2380,7 @@ class HttpRequester(BaseModelWithDeprecations):
2363
2380
  },
2364
2381
  },
2365
2382
  ],
2366
- title="Request Body Payload to be send as a part of the API request.",
2367
- )
2368
- request_headers: Optional[Union[Dict[str, str], str]] = Field(
2369
- None,
2370
- description="Return any non-auth headers. Authentication headers will overwrite any overlapping headers returned from this method.",
2371
- examples=[{"Output-Format": "JSON"}, {"Version": "{{ config['version'] }}"}],
2372
- title="Request Headers",
2373
- )
2374
- request_parameters: Optional[Union[Dict[str, Union[str, QueryProperties]], str]] = Field(
2375
- None,
2376
- description="Specifies the query parameters that should be set on an outgoing HTTP request given the inputs.",
2377
- examples=[
2378
- {"unit": "day"},
2379
- {
2380
- "query": 'last_event_time BETWEEN TIMESTAMP "{{ stream_interval.start_time }}" AND TIMESTAMP "{{ stream_interval.end_time }}"'
2381
- },
2382
- {"searchIn": "{{ ','.join(config.get('search_in', [])) }}"},
2383
- {"sort_by[asc]": "updated_at"},
2384
- ],
2385
- title="Query Parameters",
2383
+ title="Request Body",
2386
2384
  )
2387
2385
  error_handler: Optional[
2388
2386
  Union[DefaultErrorHandler, CompositeErrorHandler, CustomErrorHandler]
@@ -2475,7 +2473,7 @@ class PropertiesFromEndpoint(BaseModel):
2475
2473
  description="Describes the path to the field that should be extracted",
2476
2474
  examples=[["name"]],
2477
2475
  )
2478
- retriever: Union[CustomRetriever, SimpleRetriever] = Field(
2476
+ retriever: Union[SimpleRetriever, CustomRetriever] = Field(
2479
2477
  ...,
2480
2478
  description="Requester component that describes how to fetch the properties to query from a remote API endpoint.",
2481
2479
  )
@@ -2526,19 +2524,19 @@ class SimpleRetriever(BaseModel):
2526
2524
  )
2527
2525
  decoder: Optional[
2528
2526
  Union[
2529
- CsvDecoder,
2530
- GzipDecoder,
2531
2527
  JsonDecoder,
2528
+ XmlDecoder,
2529
+ CsvDecoder,
2532
2530
  JsonlDecoder,
2531
+ GzipDecoder,
2533
2532
  IterableDecoder,
2534
- XmlDecoder,
2535
2533
  ZipfileDecoder,
2536
2534
  CustomDecoder,
2537
2535
  ]
2538
2536
  ] = Field(
2539
2537
  None,
2540
2538
  description="Component decoding the response so records can be extracted.",
2541
- title="Decoder",
2539
+ title="HTTP Response Format",
2542
2540
  )
2543
2541
  record_selector: RecordSelector = Field(
2544
2542
  ...,
@@ -1,11 +1,10 @@
1
1
  #
2
2
  # Copyright (c) 2024 Airbyte, Inc., all rights reserved.
3
3
  #
4
-
5
-
4
+ from abc import ABC, abstractmethod
6
5
  from copy import deepcopy
7
6
  from dataclasses import InitVar, dataclass, field
8
- from typing import Any, List, Mapping, MutableMapping, Optional, Union
7
+ from typing import Any, Dict, List, Mapping, MutableMapping, Optional, Union
9
8
 
10
9
  import dpath
11
10
  from typing_extensions import deprecated
@@ -16,7 +15,7 @@ from airbyte_cdk.sources.declarative.retrievers.retriever import Retriever
16
15
  from airbyte_cdk.sources.declarative.schema.schema_loader import SchemaLoader
17
16
  from airbyte_cdk.sources.declarative.transformations import RecordTransformation
18
17
  from airbyte_cdk.sources.source import ExperimentalClassWarning
19
- from airbyte_cdk.sources.types import Config, StreamSlice, StreamState
18
+ from airbyte_cdk.sources.types import Config
20
19
 
21
20
  AIRBYTE_DATA_TYPES: Mapping[str, MutableMapping[str, Any]] = {
22
21
  "string": {"type": ["null", "string"]},
@@ -114,6 +113,38 @@ class SchemaTypeIdentifier:
114
113
  )
115
114
 
116
115
 
116
+ @deprecated("This class is experimental. Use at your own risk.", category=ExperimentalClassWarning)
117
+ class AdditionalPropertyFieldsInferrer(ABC):
118
+ """
119
+ Infers additional fields to be added to each property. For example, if this inferrer returns {"toto": "tata"}, a property that would have looked like this:
120
+ ```
121
+ "properties": {
122
+ "Id": {
123
+ "type": ["null", "string"],
124
+ },
125
+ <...>
126
+ }
127
+ ```
128
+ ... will look like this:
129
+ ```
130
+ "properties": {
131
+ "Id": {
132
+ "type": ["null", "string"],
133
+ "toto": "tata"
134
+ },
135
+ <...>
136
+ }
137
+ ```
138
+ """
139
+
140
+ @abstractmethod
141
+ def infer(self, property_definition: MutableMapping[str, Any]) -> MutableMapping[str, Any]:
142
+ """
143
+ Infers additional property fields from the given property definition.
144
+ """
145
+ pass
146
+
147
+
117
148
  @deprecated("This class is experimental. Use at your own risk.", category=ExperimentalClassWarning)
118
149
  @dataclass
119
150
  class DynamicSchemaLoader(SchemaLoader):
@@ -126,6 +157,8 @@ class DynamicSchemaLoader(SchemaLoader):
126
157
  parameters: InitVar[Mapping[str, Any]]
127
158
  schema_type_identifier: SchemaTypeIdentifier
128
159
  schema_transformations: List[RecordTransformation] = field(default_factory=lambda: [])
160
+ additional_property_fields_inferrer: Optional[AdditionalPropertyFieldsInferrer] = None
161
+ allow_additional_properties: bool = True
129
162
 
130
163
  def get_json_schema(self) -> Mapping[str, Any]:
131
164
  """
@@ -149,22 +182,26 @@ class DynamicSchemaLoader(SchemaLoader):
149
182
  property_definition,
150
183
  self.schema_type_identifier.type_pointer,
151
184
  )
185
+
186
+ value.update(
187
+ self.additional_property_fields_inferrer.infer(property_definition)
188
+ if self.additional_property_fields_inferrer
189
+ else {}
190
+ )
152
191
  properties[key] = value
153
192
 
154
- transformed_properties = self._transform(properties, {})
193
+ transformed_properties = self._transform(properties)
155
194
 
156
195
  return {
157
196
  "$schema": "https://json-schema.org/draft-07/schema#",
158
197
  "type": "object",
159
- "additionalProperties": True,
198
+ "additionalProperties": self.allow_additional_properties,
160
199
  "properties": transformed_properties,
161
200
  }
162
201
 
163
202
  def _transform(
164
203
  self,
165
204
  properties: Mapping[str, Any],
166
- stream_state: StreamState,
167
- stream_slice: Optional[StreamSlice] = None,
168
205
  ) -> Mapping[str, Any]:
169
206
  for transformation in self.schema_transformations:
170
207
  transformation.transform(
@@ -190,7 +227,7 @@ class DynamicSchemaLoader(SchemaLoader):
190
227
  self,
191
228
  raw_schema: MutableMapping[str, Any],
192
229
  field_type_path: Optional[List[Union[InterpolatedString, str]]],
193
- ) -> Union[Mapping[str, Any], List[Mapping[str, Any]]]:
230
+ ) -> Dict[str, Any]:
194
231
  """
195
232
  Determines the JSON Schema type for a field, supporting nullable and combined types.
196
233
  """
@@ -220,7 +257,7 @@ class DynamicSchemaLoader(SchemaLoader):
220
257
  f"Invalid data type. Available string or two items list of string. Got {mapped_field_type}."
221
258
  )
222
259
 
223
- def _resolve_complex_type(self, complex_type: ComplexFieldType) -> Mapping[str, Any]:
260
+ def _resolve_complex_type(self, complex_type: ComplexFieldType) -> Dict[str, Any]:
224
261
  if not complex_type.items:
225
262
  return self._get_airbyte_type(complex_type.field_type)
226
263
 
@@ -255,14 +292,14 @@ class DynamicSchemaLoader(SchemaLoader):
255
292
  return field_type
256
293
 
257
294
  @staticmethod
258
- def _get_airbyte_type(field_type: str) -> MutableMapping[str, Any]:
295
+ def _get_airbyte_type(field_type: str) -> Dict[str, Any]:
259
296
  """
260
297
  Maps a field type to its corresponding Airbyte type definition.
261
298
  """
262
299
  if field_type not in AIRBYTE_DATA_TYPES:
263
300
  raise ValueError(f"Invalid Airbyte data type: {field_type}")
264
301
 
265
- return deepcopy(AIRBYTE_DATA_TYPES[field_type])
302
+ return deepcopy(AIRBYTE_DATA_TYPES[field_type]) # type: ignore # a copy of a dict should be a dict, not a MutableMapping
266
303
 
267
304
  def _extract_data(
268
305
  self,
@@ -2,6 +2,8 @@
2
2
 
3
3
  from typing import Any, Dict, List, Union, overload
4
4
 
5
+ from airbyte_protocol_dataclasses.models import DestinationSyncMode
6
+
5
7
  from airbyte_cdk.models import (
6
8
  ConfiguredAirbyteCatalog,
7
9
  ConfiguredAirbyteStream,
@@ -32,6 +34,12 @@ class ConfiguredAirbyteStreamBuilder:
32
34
  self._stream["sync_mode"] = sync_mode.name
33
35
  return self
34
36
 
37
+ def with_destination_sync_mode(
38
+ self, sync_mode: DestinationSyncMode
39
+ ) -> "ConfiguredAirbyteStreamBuilder":
40
+ self._stream["destination_sync_mode"] = sync_mode.name
41
+ return self
42
+
35
43
  def with_primary_key(self, pk: List[List[str]]) -> "ConfiguredAirbyteStreamBuilder":
36
44
  self._stream["primary_key"] = pk
37
45
  self._stream["stream"]["source_defined_primary_key"] = pk # type: ignore # we assume that self._stream["stream"] is a Dict[str, Any]
@@ -58,7 +66,7 @@ class CatalogBuilder:
58
66
  def with_stream(
59
67
  self,
60
68
  name: Union[str, ConfiguredAirbyteStreamBuilder],
61
- sync_mode: Union[SyncMode, None] = None,
69
+ sync_mode: SyncMode = SyncMode.full_refresh,
62
70
  ) -> "CatalogBuilder":
63
71
  # As we are introducing a fully fledge ConfiguredAirbyteStreamBuilder, we would like to deprecate the previous interface
64
72
  # with_stream(str, SyncMode)
@@ -72,7 +72,11 @@ class HttpRequest:
72
72
  elif isinstance(body, bytes):
73
73
  return json.loads(body.decode()) # type: ignore # assumes return type of Mapping[str, Any]
74
74
  elif isinstance(body, str):
75
- return json.loads(body) # type: ignore # assumes return type of Mapping[str, Any]
75
+ try:
76
+ return json.loads(body) # type: ignore # assumes return type of Mapping[str, Any]
77
+ except json.JSONDecodeError:
78
+ # one of the body is a mapping while the other isn't so comparison should fail anyway
79
+ return None
76
80
  return None
77
81
 
78
82
  @staticmethod
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: airbyte-cdk
3
- Version: 6.48.6
3
+ Version: 6.48.7.dev0
4
4
  Summary: A framework for writing Airbyte Connectors.
5
5
  Home-page: https://airbyte.com
6
6
  License: MIT
@@ -23,7 +23,7 @@ Provides-Extra: sql
23
23
  Provides-Extra: vector-db-based
24
24
  Requires-Dist: Jinja2 (>=3.1.2,<3.2.0)
25
25
  Requires-Dist: PyYAML (>=6.0.1,<7.0.0)
26
- Requires-Dist: airbyte-protocol-models-dataclasses (>=0.15,<0.16)
26
+ Requires-Dist: airbyte-protocol-models-dataclasses (==0.15.0.dev1746621859)
27
27
  Requires-Dist: anyascii (>=0.3.2,<0.4.0)
28
28
  Requires-Dist: avro (>=1.11.2,<1.13.0) ; extra == "file-based"
29
29
  Requires-Dist: backoff
@@ -23,7 +23,7 @@ airbyte_cdk/connector_builder/test_reader/message_grouper.py,sha256=84BAEPIBHMq3
23
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
- airbyte_cdk/destinations/destination.py,sha256=CIq-yb8C_0QvcKCtmStaHfiqn53GEfRAIGGCkJhKP1Q,5880
26
+ airbyte_cdk/destinations/destination.py,sha256=VLuzaVniWDKtXqJzCE1yLppLGm9SvwucI3Pz82vOzgU,6755
27
27
  airbyte_cdk/destinations/vector_db_based/README.md,sha256=QAe8c_1Afme4r2TCE10cTSaxUE3zgCBuArSuRQqK8tA,2115
28
28
  airbyte_cdk/destinations/vector_db_based/__init__.py,sha256=eAkzwTjBbXBhJ5GfPO5I53Zgpv5xQFLRQS8n4nuyPt0,1006
29
29
  airbyte_cdk/destinations/vector_db_based/config.py,sha256=1u87eibIWLZ_wuaCvE3yp5ayguM9dGhGXbT8agmkUBg,12468
@@ -47,7 +47,7 @@ airbyte_cdk/manifest_migrations/migrations/http_requester_request_body_json_data
47
47
  airbyte_cdk/manifest_migrations/migrations/http_requester_url_base_to_url.py,sha256=EX1MVYVpoWypA28qoH48wA0SYZjGdlR8bcSixTDzfgo,1346
48
48
  airbyte_cdk/manifest_migrations/migrations/registry.yaml,sha256=K5KBQ2C1T_dWExEJFuEAe1VO_QqOijOCh90rnUOCEyc,960
49
49
  airbyte_cdk/manifest_migrations/migrations_registry.py,sha256=zly2fwaOxDukqC7eowzrDlvhA2v71FjW74kDzvRXhSY,2619
50
- airbyte_cdk/models/__init__.py,sha256=Et9wJWs5VOWynGbb-3aJRhsdAHAiLkNNLxdwqJAuqkw,2114
50
+ airbyte_cdk/models/__init__.py,sha256=2_fM0Vms2athSn3MDsISG9JXlfKqaeKRuLR0rudQvoc,2218
51
51
  airbyte_cdk/models/airbyte_protocol.py,sha256=oZdKsZ7yPjUt9hvxdWNpxCtgjSV2RWhf4R9Np03sqyY,3613
52
52
  airbyte_cdk/models/airbyte_protocol_serializers.py,sha256=s6SaFB2CMrG_7jTQGn_fhFbQ1FUxhCxf5kq2RWGHMVI,1749
53
53
  airbyte_cdk/models/connector_metadata.py,sha256=Lwb0JKiWvnqHduXjHHgBBBhTsGoLiNjxbG93W_OjcKQ,2875
@@ -89,7 +89,7 @@ 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=AK65U441O1kjmTnURofXyxDVyLkwCI-mVNflOdVpQM8,166443
92
+ airbyte_cdk/sources/declarative/declarative_component_schema.yaml,sha256=iWOtZ5staQtx0FZ4CSruEqyxdSO3-4SfwIQ1nw_bY_w,166744
93
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
@@ -133,7 +133,7 @@ airbyte_cdk/sources/declarative/migrations/legacy_to_per_partition_state_migrati
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
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=CXk0TwSGrpEwtbrfa8PSt6JZxpov0NqjTpEEu9Pv0OM,118040
136
+ airbyte_cdk/sources/declarative/models/declarative_component_schema.py,sha256=P0l-NiKm873uBZ0x6vRJK2u4P-XPTGeTWMnhafKryRw,117940
137
137
  airbyte_cdk/sources/declarative/parsers/__init__.py,sha256=ZnqYNxHsKCgO38IwB34RQyRMXTs4GTvlRi3ImKnIioo,61
138
138
  airbyte_cdk/sources/declarative/parsers/custom_code_compiler.py,sha256=nlVvHC511NUyDEEIRBkoeDTAvLqKNp-hRy8D19z8tdk,5941
139
139
  airbyte_cdk/sources/declarative/parsers/custom_exceptions.py,sha256=wnRUP0Xeru9Rbu5OexXSDN9QWDo8YU4tT9M2LDVOgGA,802
@@ -210,7 +210,7 @@ airbyte_cdk/sources/declarative/retrievers/retriever.py,sha256=XPLs593Xv8c5cKMc3
210
210
  airbyte_cdk/sources/declarative/retrievers/simple_retriever.py,sha256=O7qpM71L1_ATIbEKa8y658jdiSJSPw0KmuGKgnaruQU,31008
211
211
  airbyte_cdk/sources/declarative/schema/__init__.py,sha256=xU45UvM5O4c1PSM13UHpCdh5hpW3HXy9vRRGEiAC1rg,795
212
212
  airbyte_cdk/sources/declarative/schema/default_schema_loader.py,sha256=UnbzlExmwoQiVV8zDg4lhAEaqA_0pRfwbMRe8yqOuWk,1834
213
- airbyte_cdk/sources/declarative/schema/dynamic_schema_loader.py,sha256=J8Q_iJYhcSQLWyt0bTZCbDAGpxt9G8FCc6Q9jtGsNzw,10703
213
+ airbyte_cdk/sources/declarative/schema/dynamic_schema_loader.py,sha256=pdQUtQXhT8VDm1wBlLF9bqYyx_wMSKOai7qyDVGUgXI,11939
214
214
  airbyte_cdk/sources/declarative/schema/inline_schema_loader.py,sha256=bVETE10hRsatRJq3R3BeyRR0wIoK3gcP1gcpVRQ_P5U,464
215
215
  airbyte_cdk/sources/declarative/schema/json_file_schema_loader.py,sha256=5Wl-fqW-pVf_dxJ4yGHMAFfC4JjKHYJhqFJT1xA57F4,4177
216
216
  airbyte_cdk/sources/declarative/schema/schema_loader.py,sha256=kjt8v0N5wWKA5zyLnrDLxf1PJKdUqvQq2RVnAOAzNSY,379
@@ -364,12 +364,12 @@ airbyte_cdk/sql/shared/catalog_providers.py,sha256=qiahORhtN6qBUGHhSKmzE00uC4i6W
364
364
  airbyte_cdk/sql/shared/sql_processor.py,sha256=1CwfC3fp9dWnHBpKtly7vGduf9ho_MahiwxGFcULG3Y,27687
365
365
  airbyte_cdk/sql/types.py,sha256=XEIhRAo_ASd0kVLBkdLf5bHiRhNple-IJrC9TibcDdY,5880
366
366
  airbyte_cdk/test/__init__.py,sha256=f_XdkOg4_63QT2k3BbKY34209lppwgw-svzfZstQEq4,199
367
- airbyte_cdk/test/catalog_builder.py,sha256=-y05Cz1x0Dlk6oE9LSKhCozssV2gYBNtMdV5YYOPOtk,3015
367
+ airbyte_cdk/test/catalog_builder.py,sha256=b8sg1smzqSTNkwD0KUTZZin7tRFrjScco9v_RxKFYSU,3296
368
368
  airbyte_cdk/test/entrypoint_wrapper.py,sha256=TyUmVJyIuGelAv6y8Wy_BnwqIRw_drjfZWKlroljCuQ,9951
369
369
  airbyte_cdk/test/mock_http/__init__.py,sha256=jE5kC6CQ0OXkTqKhciDnNVZHesBFVIA2YvkdFGwva7k,322
370
370
  airbyte_cdk/test/mock_http/matcher.py,sha256=4Qj8UnJKZIs-eodshryce3SN1Ayc8GZpBETmP6hTEyc,1446
371
371
  airbyte_cdk/test/mock_http/mocker.py,sha256=XgsjMtVoeMpRELPyALgrkHFauH9H5irxrz1Kcxh2yFY,8013
372
- airbyte_cdk/test/mock_http/request.py,sha256=tdB8cqk2vLgCDTOKffBKsM06llYs4ZecgtH6DKyx6yY,4112
372
+ airbyte_cdk/test/mock_http/request.py,sha256=nct71fBILqy-PP4TZAkRBor--w4CJWWZZ83w9PLklok,4304
373
373
  airbyte_cdk/test/mock_http/response.py,sha256=s4-cQQqTtmeej0pQDWqmG0vUWpHS-93lIWMpW3zSVyU,662
374
374
  airbyte_cdk/test/mock_http/response_builder.py,sha256=F-v7ebftqGj7YVIMLKdodmU9U8Dq8aIyllWGo2NGwHc,8331
375
375
  airbyte_cdk/test/standard_tests/__init__.py,sha256=YS2bghoGmQ-4GNIbe6RuEmvV-V1kpM1OyxTpebrs0Ig,1338
@@ -408,9 +408,9 @@ airbyte_cdk/utils/slice_hasher.py,sha256=EDxgROHDbfG-QKQb59m7h_7crN1tRiawdf5uU7G
408
408
  airbyte_cdk/utils/spec_schema_transformations.py,sha256=-5HTuNsnDBAhj-oLeQXwpTGA0HdcjFOf2zTEMUTTg_Y,816
409
409
  airbyte_cdk/utils/stream_status_utils.py,sha256=ZmBoiy5HVbUEHAMrUONxZvxnvfV9CesmQJLDTAIWnWw,1171
410
410
  airbyte_cdk/utils/traced_exception.py,sha256=C8uIBuCL_E4WnBAOPSxBicD06JAldoN9fGsQDp463OY,6292
411
- airbyte_cdk-6.48.6.dist-info/LICENSE.txt,sha256=Wfe61S4BaGPj404v8lrAbvhjYR68SHlkzeYrg3_bbuM,1051
412
- airbyte_cdk-6.48.6.dist-info/LICENSE_SHORT,sha256=aqF6D1NcESmpn-cqsxBtszTEnHKnlsp8L4x9wAh3Nxg,55
413
- airbyte_cdk-6.48.6.dist-info/METADATA,sha256=ukLCWdp4GYARrBEW7wQubufsruhncIeEhAvMFweXs9Y,6343
414
- airbyte_cdk-6.48.6.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
415
- airbyte_cdk-6.48.6.dist-info/entry_points.txt,sha256=AKWbEkHfpzzk9nF9tqBUaw1MbvTM4mGtEzmZQm0ZWvM,139
416
- airbyte_cdk-6.48.6.dist-info/RECORD,,
411
+ airbyte_cdk-6.48.7.dev0.dist-info/LICENSE.txt,sha256=Wfe61S4BaGPj404v8lrAbvhjYR68SHlkzeYrg3_bbuM,1051
412
+ airbyte_cdk-6.48.7.dev0.dist-info/LICENSE_SHORT,sha256=aqF6D1NcESmpn-cqsxBtszTEnHKnlsp8L4x9wAh3Nxg,55
413
+ airbyte_cdk-6.48.7.dev0.dist-info/METADATA,sha256=KaGGArfmNfNBkCp4AEJtH66h_vzlO5e7jrKZz2Az_Tg,6358
414
+ airbyte_cdk-6.48.7.dev0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
415
+ airbyte_cdk-6.48.7.dev0.dist-info/entry_points.txt,sha256=AKWbEkHfpzzk9nF9tqBUaw1MbvTM4mGtEzmZQm0ZWvM,139
416
+ airbyte_cdk-6.48.7.dev0.dist-info/RECORD,,