airbyte-cdk 6.11.2.dev1__py3-none-any.whl → 6.12.0rc1__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.
@@ -1897,6 +1897,56 @@ definitions:
1897
1897
  $parameters:
1898
1898
  type: object
1899
1899
  additionalProperties: true
1900
+ ZipfileDecoder:
1901
+ title: Zipfile Decoder
1902
+ description: Decoder for response data that is returned as zipfile(s).
1903
+ type: object
1904
+ additionalProperties: true
1905
+ required:
1906
+ - type
1907
+ properties:
1908
+ type:
1909
+ type: string
1910
+ enum: [ZipfileDecoder]
1911
+ parser:
1912
+ title: Parser
1913
+ description: Parser to parse the decompressed data from the zipfile(s).
1914
+ anyOf:
1915
+ - "$ref": "#/definitions/JsonParser"
1916
+ - "$ref": "#/definitions/CustomParser"
1917
+ JsonParser:
1918
+ title: JsonParser
1919
+ description: Parser used for parsing str, bytes, or bytearray data and returning data in a dictionary format.
1920
+ type: object
1921
+ additionalProperties: true
1922
+ required:
1923
+ - type
1924
+ properties:
1925
+ type:
1926
+ type: string
1927
+ enum: [JsonParser]
1928
+ CustomParser:
1929
+ title: Custom Parser
1930
+ description: Use this to implement custom parser logic.
1931
+ type: object
1932
+ additionalProperties: true
1933
+ required:
1934
+ - type
1935
+ - class_name
1936
+ properties:
1937
+ type:
1938
+ type: string
1939
+ enum: [CustomParser]
1940
+ class_name:
1941
+ title: Class Name
1942
+ description: Fully-qualified name of the class that will be implementing the custom decoding. Has to be a sub class of Parser. The format is `source_<name>.<package>.<class_name>`.
1943
+ type: string
1944
+ additionalProperties: true
1945
+ examples:
1946
+ - "source_rivendell.components.ElvishParser"
1947
+ $parameters:
1948
+ type: object
1949
+ additionalProperties: true
1900
1950
  ListPartitionRouter:
1901
1951
  title: List Partition Router
1902
1952
  description: A Partition router that specifies a list of attributes where each attribute describes a portion of the complete data set for a stream. During a sync, each value is iterated over and can be used as input to outbound API requests.
@@ -2130,61 +2180,65 @@ definitions:
2130
2180
  - extract_output
2131
2181
  properties:
2132
2182
  consent_url:
2133
- title: Consent URL
2183
+ title: DeclarativeOAuth Consent URL
2134
2184
  type: string
2135
2185
  description: |-
2136
2186
  The DeclarativeOAuth Specific string URL string template to initiate the authentication.
2137
2187
  The placeholders are replaced during the processing to provide neccessary values.
2138
2188
  examples:
2139
- - https://domain.host.com/marketing_api/auth?{client_id_key}={{client_id_key}}&{redirect_uri_key}={urlEncoder:{{redirect_uri_key}}}&{state_key}={{state_key}}
2140
- - https://endpoint.host.com/oauth2/authorize?{client_id_key}={{client_id_key}}&{redirect_uri_key}={urlEncoder:{{redirect_uri_key}}}&{scope_key}={urlEncoder:{{scope_key}}}&{state_key}={{state_key}}&subdomain={subdomain}
2189
+ - consent_url: https://domain.host.com/marketing_api/auth?{client_id_key}={{client_id_key}}&{redirect_uri_key}={urlEncoder:{{redirect_uri_key}}}&{state_key}={{state_key}}
2190
+ - consent_url: https://endpoint.host.com/oauth2/authorize?{client_id_key}={{client_id_key}}&{redirect_uri_key}={urlEncoder:{{redirect_uri_key}}}&{scope_key}={urlEncoder:{{scope_key}}}&{state_key}={{state_key}}&subdomain={subdomain}
2141
2191
  scope:
2142
- title: Scopes
2192
+ title: (Optional) DeclarativeOAuth Scope
2143
2193
  type: string
2144
2194
  description: |-
2145
2195
  The DeclarativeOAuth Specific string of the scopes needed to be grant for authenticated user.
2146
2196
  examples:
2147
- - user:read user:read_orders workspaces:read
2197
+ - scope: user:read user:read_orders workspaces:read
2148
2198
  access_token_url:
2149
- title: Access Token URL
2199
+ title: DeclarativeOAuth Access Token URL
2150
2200
  type: string
2151
2201
  description: |-
2152
2202
  The DeclarativeOAuth Specific URL templated string to obtain the `access_token`, `refresh_token` etc.
2153
2203
  The placeholders are replaced during the processing to provide neccessary values.
2154
2204
  examples:
2155
- - https://auth.host.com/oauth2/token?{client_id_key}={{client_id_key}}&{client_secret_key}={{client_secret_key}}&{auth_code_key}={{auth_code_key}}&{redirect_uri_key}={urlEncoder:{{redirect_uri_key}}}
2205
+ - access_token_url: https://auth.host.com/oauth2/token?{client_id_key}={{client_id_key}}&{client_secret_key}={{client_secret_key}}&{auth_code_key}={{auth_code_key}}&{redirect_uri_key}={urlEncoder:{{redirect_uri_key}}}
2156
2206
  access_token_headers:
2157
- title: Access Token Headers
2207
+ title: (Optional) DeclarativeOAuth Access Token Headers
2158
2208
  type: object
2159
2209
  additionalProperties: true
2160
2210
  description: |-
2161
2211
  The DeclarativeOAuth Specific optional headers to inject while exchanging the `auth_code` to `access_token` during `completeOAuthFlow` step.
2162
2212
  examples:
2163
- - {"Authorization": "Basic {base64Encoder:{client_id}:{client_secret}}"}
2213
+ - access_token_headers:
2214
+ {
2215
+ "Authorization": "Basic {base64Encoder:{client_id}:{client_secret}}",
2216
+ }
2164
2217
  access_token_params:
2165
- title: Access Token Query Params (Json Encoded)
2218
+ title: (Optional) DeclarativeOAuth Access Token Query Params (Json Encoded)
2166
2219
  type: object
2167
2220
  additionalProperties: true
2168
2221
  description: |-
2169
2222
  The DeclarativeOAuth Specific optional query parameters to inject while exchanging the `auth_code` to `access_token` during `completeOAuthFlow` step.
2170
2223
  When this property is provided, the query params will be encoded as `Json` and included in the outgoing API request.
2171
2224
  examples:
2172
- - {
2173
- "{auth_code_key}": "{{auth_code_key}}",
2174
- "{client_id_key}": "{{client_id_key}}",
2175
- "{client_secret_key}": "{{client_secret_key}}",
2176
- }
2225
+ - access_token_params:
2226
+ {
2227
+ "{auth_code_key}": "{{auth_code_key}}",
2228
+ "{client_id_key}": "{{client_id_key}}",
2229
+ "{client_secret_key}": "{{client_secret_key}}",
2230
+ }
2177
2231
  extract_output:
2178
- title: Extract Output
2232
+ title: DeclarativeOAuth Extract Output
2179
2233
  type: array
2180
2234
  items:
2181
2235
  type: string
2182
2236
  description: |-
2183
2237
  The DeclarativeOAuth Specific list of strings to indicate which keys should be extracted and returned back to the input config.
2184
2238
  examples:
2185
- - ["access_token", "refresh_token", "other_field"]
2239
+ - extract_output: ["access_token", "refresh_token", "other_field"]
2186
2240
  state:
2187
- title: Configurable State Query Param
2241
+ title: (Optional) DeclarativeOAuth Configurable State Query Param
2188
2242
  type: object
2189
2243
  additionalProperties: true
2190
2244
  required:
@@ -2199,49 +2253,49 @@ definitions:
2199
2253
  max:
2200
2254
  type: integer
2201
2255
  examples:
2202
- - { "min": 7, "max": 128 }
2256
+ - state: { "min": 7, "max": 128 }
2203
2257
  client_id_key:
2204
- title: Client ID Key Override
2258
+ title: (Optional) DeclarativeOAuth Client ID Key Override
2205
2259
  type: string
2206
2260
  description: |-
2207
2261
  The DeclarativeOAuth Specific optional override to provide the custom `client_id` key name, if required by data-provider.
2208
2262
  examples:
2209
- - "my_custom_client_id_key_name"
2263
+ - client_id_key: "my_custom_client_id_key_name"
2210
2264
  client_secret_key:
2211
- title: Client Secret Key Override
2265
+ title: (Optional) DeclarativeOAuth Client Secret Key Override
2212
2266
  type: string
2213
2267
  description: |-
2214
2268
  The DeclarativeOAuth Specific optional override to provide the custom `client_secret` key name, if required by data-provider.
2215
2269
  examples:
2216
- - "my_custom_client_secret_key_name"
2270
+ - client_secret_key: "my_custom_client_secret_key_name"
2217
2271
  scope_key:
2218
- title: Scopes Key Override
2272
+ title: (Optional) DeclarativeOAuth Scope Key Override
2219
2273
  type: string
2220
2274
  description: |-
2221
2275
  The DeclarativeOAuth Specific optional override to provide the custom `scope` key name, if required by data-provider.
2222
2276
  examples:
2223
- - "my_custom_scope_key_key_name"
2277
+ - scope_key: "my_custom_scope_key_key_name"
2224
2278
  state_key:
2225
- title: State Key Override
2279
+ title: (Optional) DeclarativeOAuth State Key Override
2226
2280
  type: string
2227
2281
  description: |-
2228
2282
  The DeclarativeOAuth Specific optional override to provide the custom `state` key name, if required by data-provider.
2229
2283
  examples:
2230
- - "my_custom_state_key_key_name"
2284
+ - state_key: "my_custom_state_key_key_name"
2231
2285
  auth_code_key:
2232
- title: Auth Code Key Override
2286
+ title: (Optional) DeclarativeOAuth Auth Code Key Override
2233
2287
  type: string
2234
2288
  description: |-
2235
2289
  The DeclarativeOAuth Specific optional override to provide the custom `code` key name to something like `auth_code` or `custom_auth_code`, if required by data-provider.
2236
2290
  examples:
2237
- - "my_custom_auth_code_key_name"
2291
+ - auth_code_key: "my_custom_auth_code_key_name"
2238
2292
  redirect_uri_key:
2239
- title: Redirect URI Key Override
2293
+ title: (Optional) DeclarativeOAuth Redirect URI Key Override
2240
2294
  type: string
2241
2295
  description: |-
2242
2296
  The DeclarativeOAuth Specific optional override to provide the custom `redirect_uri` key name to something like `callback_uri`, if required by data-provider.
2243
2297
  examples:
2244
- - "my_custom_redirect_uri_key_name"
2298
+ - redirect_uri_key: "my_custom_redirect_uri_key_name"
2245
2299
  complete_oauth_output_specification:
2246
2300
  title: "OAuth output specification"
2247
2301
  description: |-
@@ -7,5 +7,6 @@ from airbyte_cdk.sources.declarative.decoders.json_decoder import JsonDecoder, J
7
7
  from airbyte_cdk.sources.declarative.decoders.noop_decoder import NoopDecoder
8
8
  from airbyte_cdk.sources.declarative.decoders.pagination_decoder_decorator import PaginationDecoderDecorator
9
9
  from airbyte_cdk.sources.declarative.decoders.xml_decoder import XmlDecoder
10
+ from airbyte_cdk.sources.declarative.decoders.zipfile_decoder import ZipfileDecoder
10
11
 
11
- __all__ = ["Decoder", "JsonDecoder", "JsonlDecoder", "IterableDecoder", "GzipJsonDecoder", "NoopDecoder", "PaginationDecoderDecorator", "XmlDecoder"]
12
+ __all__ = ["Decoder", "JsonDecoder", "JsonlDecoder", "IterableDecoder", "GzipJsonDecoder", "NoopDecoder", "PaginationDecoderDecorator", "XmlDecoder", "ZipfileDecoder"]
@@ -0,0 +1,7 @@
1
+ #
2
+ # Copyright (c) 2024 Airbyte, Inc., all rights reserved.
3
+ #
4
+
5
+ from airbyte_cdk.sources.declarative.decoders.parsers.parsers import Parser, JsonParser
6
+
7
+ __all__ = ["Parser", "JsonParser"]
@@ -0,0 +1,49 @@
1
+ #
2
+ # Copyright (c) 2024 Airbyte, Inc., all rights reserved.
3
+ #
4
+
5
+ import json
6
+ import logging
7
+ from abc import abstractmethod
8
+ from dataclasses import InitVar, dataclass
9
+ from typing import Any, Generator, Mapping, MutableMapping, Union
10
+
11
+ logger = logging.getLogger("airbyte")
12
+
13
+
14
+ @dataclass
15
+ class Parser:
16
+ """
17
+ Parser strategy to convert str, bytes, or bytearray data into MutableMapping[str, Any].
18
+ """
19
+
20
+ @abstractmethod
21
+ def parse(
22
+ self, data: Union[str, bytes, bytearray]
23
+ ) -> Generator[MutableMapping[str, Any], None, None]:
24
+ pass
25
+
26
+
27
+ @dataclass
28
+ class JsonParser(Parser):
29
+ """
30
+ Parser strategy for converting JSON-structure str, bytes, or bytearray data into MutableMapping[str, Any].
31
+ """
32
+
33
+ parameters: InitVar[Mapping[str, Any]]
34
+
35
+ def parse(
36
+ self, data: Union[str, bytes, bytearray]
37
+ ) -> Generator[MutableMapping[str, Any], None, None]:
38
+ try:
39
+ body_json = json.loads(data)
40
+ except json.JSONDecodeError:
41
+ logger.warning(f"Data cannot be parsed into json: {data=}")
42
+ yield {}
43
+
44
+ if not isinstance(body_json, list):
45
+ body_json = [body_json]
46
+ if len(body_json) == 0:
47
+ yield {}
48
+ else:
49
+ yield from body_json
@@ -0,0 +1,54 @@
1
+ #
2
+ # Copyright (c) 2024 Airbyte, Inc., all rights reserved.
3
+ #
4
+
5
+ import gzip
6
+ import io
7
+ import logging
8
+ import zipfile
9
+ from dataclasses import InitVar, dataclass
10
+ from typing import Any, Generator, Mapping, MutableMapping, Optional
11
+
12
+ import requests
13
+
14
+ from airbyte_cdk.sources.declarative.decoders import Decoder
15
+ from airbyte_cdk.sources.declarative.decoders.parsers import JsonParser, Parser
16
+
17
+ logger = logging.getLogger("airbyte")
18
+
19
+
20
+ @dataclass
21
+ class ZipfileDecoder(Decoder):
22
+ parameters: InitVar[Mapping[str, Any]]
23
+ parser: Optional[Parser] = None
24
+
25
+ def __post_init__(self, parameters: Mapping[str, Any]) -> None:
26
+ self._parser = (
27
+ self.parser(parameters=parameters) if self.parser else JsonParser(parameters=parameters)
28
+ )
29
+
30
+ def is_stream_response(self) -> bool:
31
+ return False
32
+
33
+ def decode(
34
+ self, response: requests.Response
35
+ ) -> Generator[MutableMapping[str, Any], None, None]:
36
+ try:
37
+ zip_file = zipfile.ZipFile(io.BytesIO(response.content))
38
+ except zipfile.BadZipFile as e:
39
+ logger.exception(e)
40
+ logger.error(
41
+ f"Received an invalid zip file in response to URL: {response.request.url}. "
42
+ f"The size of the response body is: {len(response.content)}"
43
+ )
44
+ yield {}
45
+
46
+ for gzip_filename in zip_file.namelist():
47
+ with zip_file.open(gzip_filename) as file:
48
+ try:
49
+ for data in gzip.open(file):
50
+ yield from self._parser.parse(data)
51
+ except gzip.BadGzipFile as e:
52
+ logger.exception(e)
53
+ logger.error(f"Fail to read contents of zipped response: {e}")
54
+ yield {}
@@ -741,6 +741,27 @@ class GzipJsonDecoder(BaseModel):
741
741
  parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
742
742
 
743
743
 
744
+ class JsonParser(BaseModel):
745
+ class Config:
746
+ extra = Extra.allow
747
+
748
+ type: Literal["JsonParser"]
749
+
750
+
751
+ class CustomParser(BaseModel):
752
+ class Config:
753
+ extra = Extra.allow
754
+
755
+ type: Literal["CustomParser"]
756
+ class_name: str = Field(
757
+ ...,
758
+ description="Fully-qualified name of the class that will be implementing the custom decoding. Has to be a sub class of Parser. The format is `source_<name>.<package>.<class_name>`.",
759
+ examples=["source_rivendell.components.ElvishParser"],
760
+ title="Class Name",
761
+ )
762
+ parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
763
+
764
+
744
765
  class MinMaxDatetime(BaseModel):
745
766
  type: Literal["MinMaxDatetime"]
746
767
  datetime: str = Field(
@@ -795,90 +816,104 @@ class OauthConnectorInputSpecification(BaseModel):
795
816
  ...,
796
817
  description="The DeclarativeOAuth Specific string URL string template to initiate the authentication.\nThe placeholders are replaced during the processing to provide neccessary values.",
797
818
  examples=[
798
- "https://domain.host.com/marketing_api/auth?{client_id_key}={{client_id_key}}&{redirect_uri_key}={urlEncoder:{{redirect_uri_key}}}&{state_key}={{state_key}}",
799
- "https://endpoint.host.com/oauth2/authorize?{client_id_key}={{client_id_key}}&{redirect_uri_key}={urlEncoder:{{redirect_uri_key}}}&{scope_key}={urlEncoder:{{scope_key}}}&{state_key}={{state_key}}&subdomain={subdomain}",
819
+ {
820
+ "consent_url": "https://domain.host.com/marketing_api/auth?{client_id_key}={{client_id_key}}&{redirect_uri_key}={urlEncoder:{{redirect_uri_key}}}&{state_key}={{state_key}}"
821
+ },
822
+ {
823
+ "consent_url": "https://endpoint.host.com/oauth2/authorize?{client_id_key}={{client_id_key}}&{redirect_uri_key}={urlEncoder:{{redirect_uri_key}}}&{scope_key}={urlEncoder:{{scope_key}}}&{state_key}={{state_key}}&subdomain={subdomain}"
824
+ },
800
825
  ],
801
- title="Consent URL",
826
+ title="DeclarativeOAuth Consent URL",
802
827
  )
803
828
  scope: Optional[str] = Field(
804
829
  None,
805
830
  description="The DeclarativeOAuth Specific string of the scopes needed to be grant for authenticated user.",
806
- examples=["user:read user:read_orders workspaces:read"],
807
- title="Scopes",
831
+ examples=[{"scope": "user:read user:read_orders workspaces:read"}],
832
+ title="(Optional) DeclarativeOAuth Scope",
808
833
  )
809
834
  access_token_url: str = Field(
810
835
  ...,
811
836
  description="The DeclarativeOAuth Specific URL templated string to obtain the `access_token`, `refresh_token` etc.\nThe placeholders are replaced during the processing to provide neccessary values.",
812
837
  examples=[
813
- "https://auth.host.com/oauth2/token?{client_id_key}={{client_id_key}}&{client_secret_key}={{client_secret_key}}&{auth_code_key}={{auth_code_key}}&{redirect_uri_key}={urlEncoder:{{redirect_uri_key}}}"
838
+ {
839
+ "access_token_url": "https://auth.host.com/oauth2/token?{client_id_key}={{client_id_key}}&{client_secret_key}={{client_secret_key}}&{auth_code_key}={{auth_code_key}}&{redirect_uri_key}={urlEncoder:{{redirect_uri_key}}}"
840
+ }
814
841
  ],
815
- title="Access Token URL",
842
+ title="DeclarativeOAuth Access Token URL",
816
843
  )
817
844
  access_token_headers: Optional[Dict[str, Any]] = Field(
818
845
  None,
819
846
  description="The DeclarativeOAuth Specific optional headers to inject while exchanging the `auth_code` to `access_token` during `completeOAuthFlow` step.",
820
- examples=[{"Authorization": "Basic {base64Encoder:{client_id}:{client_secret}}"}],
821
- title="Access Token Headers",
847
+ examples=[
848
+ {
849
+ "access_token_headers": {
850
+ "Authorization": "Basic {base64Encoder:{client_id}:{client_secret}}"
851
+ }
852
+ }
853
+ ],
854
+ title="(Optional) DeclarativeOAuth Access Token Headers",
822
855
  )
823
856
  access_token_params: Optional[Dict[str, Any]] = Field(
824
857
  None,
825
858
  description="The DeclarativeOAuth Specific optional query parameters to inject while exchanging the `auth_code` to `access_token` during `completeOAuthFlow` step.\nWhen this property is provided, the query params will be encoded as `Json` and included in the outgoing API request.",
826
859
  examples=[
827
860
  {
828
- "{auth_code_key}": "{{auth_code_key}}",
829
- "{client_id_key}": "{{client_id_key}}",
830
- "{client_secret_key}": "{{client_secret_key}}",
861
+ "access_token_params": {
862
+ "{auth_code_key}": "{{auth_code_key}}",
863
+ "{client_id_key}": "{{client_id_key}}",
864
+ "{client_secret_key}": "{{client_secret_key}}",
865
+ }
831
866
  }
832
867
  ],
833
- title="Access Token Query Params (Json Encoded)",
868
+ title="(Optional) DeclarativeOAuth Access Token Query Params (Json Encoded)",
834
869
  )
835
870
  extract_output: List[str] = Field(
836
871
  ...,
837
872
  description="The DeclarativeOAuth Specific list of strings to indicate which keys should be extracted and returned back to the input config.",
838
- examples=[["access_token", "refresh_token", "other_field"]],
839
- title="Extract Output",
873
+ examples=[{"extract_output": ["access_token", "refresh_token", "other_field"]}],
874
+ title="DeclarativeOAuth Extract Output",
840
875
  )
841
876
  state: Optional[State] = Field(
842
877
  None,
843
878
  description="The DeclarativeOAuth Specific object to provide the criteria of how the `state` query param should be constructed,\nincluding length and complexity.",
844
- examples=[{"min": 7, "max": 128}],
845
- title="Configurable State Query Param",
879
+ examples=[{"state": {"min": 7, "max": 128}}],
880
+ title="(Optional) DeclarativeOAuth Configurable State Query Param",
846
881
  )
847
882
  client_id_key: Optional[str] = Field(
848
883
  None,
849
884
  description="The DeclarativeOAuth Specific optional override to provide the custom `client_id` key name, if required by data-provider.",
850
- examples=["my_custom_client_id_key_name"],
851
- title="Client ID Key Override",
885
+ examples=[{"client_id_key": "my_custom_client_id_key_name"}],
886
+ title="(Optional) DeclarativeOAuth Client ID Key Override",
852
887
  )
853
888
  client_secret_key: Optional[str] = Field(
854
889
  None,
855
890
  description="The DeclarativeOAuth Specific optional override to provide the custom `client_secret` key name, if required by data-provider.",
856
- examples=["my_custom_client_secret_key_name"],
857
- title="Client Secret Key Override",
891
+ examples=[{"client_secret_key": "my_custom_client_secret_key_name"}],
892
+ title="(Optional) DeclarativeOAuth Client Secret Key Override",
858
893
  )
859
894
  scope_key: Optional[str] = Field(
860
895
  None,
861
896
  description="The DeclarativeOAuth Specific optional override to provide the custom `scope` key name, if required by data-provider.",
862
- examples=["my_custom_scope_key_key_name"],
863
- title="Scopes Key Override",
897
+ examples=[{"scope_key": "my_custom_scope_key_key_name"}],
898
+ title="(Optional) DeclarativeOAuth Scope Key Override",
864
899
  )
865
900
  state_key: Optional[str] = Field(
866
901
  None,
867
902
  description="The DeclarativeOAuth Specific optional override to provide the custom `state` key name, if required by data-provider.",
868
- examples=["my_custom_state_key_key_name"],
869
- title="State Key Override",
903
+ examples=[{"state_key": "my_custom_state_key_key_name"}],
904
+ title="(Optional) DeclarativeOAuth State Key Override",
870
905
  )
871
906
  auth_code_key: Optional[str] = Field(
872
907
  None,
873
908
  description="The DeclarativeOAuth Specific optional override to provide the custom `code` key name to something like `auth_code` or `custom_auth_code`, if required by data-provider.",
874
- examples=["my_custom_auth_code_key_name"],
875
- title="Auth Code Key Override",
909
+ examples=[{"auth_code_key": "my_custom_auth_code_key_name"}],
910
+ title="(Optional) DeclarativeOAuth Auth Code Key Override",
876
911
  )
877
912
  redirect_uri_key: Optional[str] = Field(
878
913
  None,
879
914
  description="The DeclarativeOAuth Specific optional override to provide the custom `redirect_uri` key name to something like `callback_uri`, if required by data-provider.",
880
- examples=["my_custom_redirect_uri_key_name"],
881
- title="Redirect URI Key Override",
915
+ examples=[{"redirect_uri_key": "my_custom_redirect_uri_key_name"}],
916
+ title="(Optional) DeclarativeOAuth Redirect URI Key Override",
882
917
  )
883
918
 
884
919
 
@@ -1454,6 +1489,18 @@ class SessionTokenRequestApiKeyAuthenticator(BaseModel):
1454
1489
  )
1455
1490
 
1456
1491
 
1492
+ class ZipfileDecoder(BaseModel):
1493
+ class Config:
1494
+ extra = Extra.allow
1495
+
1496
+ type: Literal["ZipfileDecoder"]
1497
+ parser: Optional[Union[JsonParser, CustomParser]] = Field(
1498
+ None,
1499
+ description="Parser to parse the decompressed data from the zipfile(s).",
1500
+ title="Parser",
1501
+ )
1502
+
1503
+
1457
1504
  class ListPartitionRouter(BaseModel):
1458
1505
  type: Literal["ListPartitionRouter"]
1459
1506
  cursor_field: str = Field(
@@ -66,7 +66,9 @@ from airbyte_cdk.sources.declarative.decoders import (
66
66
  JsonlDecoder,
67
67
  PaginationDecoderDecorator,
68
68
  XmlDecoder,
69
+ ZipfileDecoder,
69
70
  )
71
+ from airbyte_cdk.sources.declarative.decoders.parsers import JsonParser
70
72
  from airbyte_cdk.sources.declarative.extractors import (
71
73
  DpathExtractor,
72
74
  RecordFilter,
@@ -224,6 +226,9 @@ from airbyte_cdk.sources.declarative.models.declarative_component_schema import
224
226
  from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
225
227
  JsonlDecoder as JsonlDecoderModel,
226
228
  )
229
+ from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
230
+ JsonParser as JsonParserModel,
231
+ )
227
232
  from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
228
233
  JwtAuthenticator as JwtAuthenticatorModel,
229
234
  )
@@ -316,6 +321,9 @@ from airbyte_cdk.sources.declarative.models.declarative_component_schema import
316
321
  from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
317
322
  XmlDecoder as XmlDecoderModel,
318
323
  )
324
+ from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
325
+ ZipfileDecoder as ZipfileDecoderModel,
326
+ )
319
327
  from airbyte_cdk.sources.declarative.partition_routers import (
320
328
  CartesianProductStreamSlicer,
321
329
  ListPartitionRouter,
@@ -323,9 +331,6 @@ from airbyte_cdk.sources.declarative.partition_routers import (
323
331
  SinglePartitionRouter,
324
332
  SubstreamPartitionRouter,
325
333
  )
326
- from airbyte_cdk.sources.declarative.partition_routers.async_job_partition_router import (
327
- AsyncJobPartitionRouter,
328
- )
329
334
  from airbyte_cdk.sources.declarative.partition_routers.substream_partition_router import (
330
335
  ParentStreamConfig,
331
336
  )
@@ -473,6 +478,7 @@ class ModelToComponentFactory:
473
478
  InlineSchemaLoaderModel: self.create_inline_schema_loader,
474
479
  JsonDecoderModel: self.create_json_decoder,
475
480
  JsonlDecoderModel: self.create_jsonl_decoder,
481
+ JsonParserModel: self.create_json_parser,
476
482
  GzipJsonDecoderModel: self.create_gzipjson_decoder,
477
483
  KeysToLowerModel: self.create_keys_to_lower_transformation,
478
484
  IterableDecoderModel: self.create_iterable_decoder,
@@ -508,6 +514,7 @@ class ModelToComponentFactory:
508
514
  ConfigComponentsResolverModel: self.create_config_components_resolver,
509
515
  StreamConfigModel: self.create_stream_config,
510
516
  ComponentMappingDefinitionModel: self.create_components_mapping_definition,
517
+ ZipfileDecoderModel: self.create_zipfile_decoder,
511
518
  }
512
519
 
513
520
  # Needed for the case where we need to perform a second parse on the fields of a custom component
@@ -1685,6 +1692,20 @@ class ModelToComponentFactory:
1685
1692
  ) -> GzipJsonDecoder:
1686
1693
  return GzipJsonDecoder(parameters={}, encoding=model.encoding)
1687
1694
 
1695
+ def create_zipfile_decoder(
1696
+ self, model: ZipfileDecoderModel, config: Config, **kwargs: Any
1697
+ ) -> ZipfileDecoder:
1698
+ parser = (
1699
+ self._create_component_from_model(model=model.parser, config=config)
1700
+ if model.parser
1701
+ else None
1702
+ )
1703
+ return ZipfileDecoder(parameters={}, parser=parser)
1704
+
1705
+ @staticmethod
1706
+ def create_json_parser(model: JsonParserModel, config: Config, **kwargs: Any) -> JsonParser:
1707
+ return JsonParser(parameters={})
1708
+
1688
1709
  @staticmethod
1689
1710
  def create_json_file_schema_loader(
1690
1711
  model: JsonFileSchemaLoaderModel, config: Config, **kwargs: Any
@@ -2231,24 +2252,18 @@ class ModelToComponentFactory:
2231
2252
  urls_extractor=urls_extractor,
2232
2253
  )
2233
2254
 
2234
- async_job_partition_router = AsyncJobPartitionRouter(
2255
+ return AsyncRetriever(
2235
2256
  job_orchestrator_factory=lambda stream_slices: AsyncJobOrchestrator(
2236
2257
  job_repository,
2237
2258
  stream_slices,
2238
- JobTracker(1),
2239
- # FIXME eventually make the number of concurrent jobs in the API configurable. Until then, we limit to 1
2259
+ JobTracker(
2260
+ 1
2261
+ ), # FIXME eventually make the number of concurrent jobs in the API configurable. Until then, we limit to 1
2240
2262
  self._message_repository,
2241
- has_bulk_parent=False,
2242
- # FIXME work would need to be done here in order to detect if a stream as a parent stream that is bulk
2263
+ has_bulk_parent=False, # FIXME work would need to be done here in order to detect if a stream as a parent stream that is bulk
2243
2264
  ),
2244
- stream_slicer=stream_slicer,
2245
- config=config,
2246
- parameters=model.parameters or {},
2247
- )
2248
-
2249
- return AsyncRetriever(
2250
2265
  record_selector=record_selector,
2251
- stream_slicer=async_job_partition_router,
2266
+ stream_slicer=stream_slicer,
2252
2267
  config=config,
2253
2268
  parameters=model.parameters or {},
2254
2269
  )
@@ -2,18 +2,10 @@
2
2
  # Copyright (c) 2022 Airbyte, Inc., all rights reserved.
3
3
  #
4
4
 
5
- from airbyte_cdk.sources.declarative.partition_routers.async_job_partition_router import AsyncJobPartitionRouter
6
5
  from airbyte_cdk.sources.declarative.partition_routers.cartesian_product_stream_slicer import CartesianProductStreamSlicer
7
6
  from airbyte_cdk.sources.declarative.partition_routers.list_partition_router import ListPartitionRouter
8
7
  from airbyte_cdk.sources.declarative.partition_routers.single_partition_router import SinglePartitionRouter
9
8
  from airbyte_cdk.sources.declarative.partition_routers.substream_partition_router import SubstreamPartitionRouter
10
9
  from airbyte_cdk.sources.declarative.partition_routers.partition_router import PartitionRouter
11
10
 
12
- __all__ = [
13
- "AsyncJobPartitionRouter",
14
- "CartesianProductStreamSlicer",
15
- "ListPartitionRouter",
16
- "SinglePartitionRouter",
17
- "SubstreamPartitionRouter",
18
- "PartitionRouter"
19
- ]
11
+ __all__ = ["CartesianProductStreamSlicer", "ListPartitionRouter", "SinglePartitionRouter", "SubstreamPartitionRouter", "PartitionRouter"]
@@ -1,8 +1,8 @@
1
1
  # Copyright (c) 2024 Airbyte, Inc., all rights reserved.
2
2
 
3
3
 
4
- from dataclasses import InitVar, dataclass
5
- from typing import Any, Iterable, Mapping, Optional
4
+ from dataclasses import InitVar, dataclass, field
5
+ from typing import Any, Callable, Iterable, Mapping, Optional
6
6
 
7
7
  from typing_extensions import deprecated
8
8
 
@@ -12,10 +12,9 @@ from airbyte_cdk.sources.declarative.async_job.job_orchestrator import (
12
12
  AsyncPartition,
13
13
  )
14
14
  from airbyte_cdk.sources.declarative.extractors.record_selector import RecordSelector
15
- from airbyte_cdk.sources.declarative.partition_routers.async_job_partition_router import (
16
- AsyncJobPartitionRouter,
17
- )
15
+ from airbyte_cdk.sources.declarative.partition_routers import SinglePartitionRouter
18
16
  from airbyte_cdk.sources.declarative.retrievers import Retriever
17
+ from airbyte_cdk.sources.declarative.stream_slicers import StreamSlicer
19
18
  from airbyte_cdk.sources.source import ExperimentalClassWarning
20
19
  from airbyte_cdk.sources.streams.core import StreamData
21
20
  from airbyte_cdk.sources.types import Config, StreamSlice, StreamState
@@ -30,10 +29,15 @@ from airbyte_cdk.utils.traced_exception import AirbyteTracedException
30
29
  class AsyncRetriever(Retriever):
31
30
  config: Config
32
31
  parameters: InitVar[Mapping[str, Any]]
32
+ job_orchestrator_factory: Callable[[Iterable[StreamSlice]], AsyncJobOrchestrator]
33
33
  record_selector: RecordSelector
34
- stream_slicer: AsyncJobPartitionRouter
34
+ stream_slicer: StreamSlicer = field(
35
+ default_factory=lambda: SinglePartitionRouter(parameters={})
36
+ )
35
37
 
36
38
  def __post_init__(self, parameters: Mapping[str, Any]) -> None:
39
+ self._job_orchestrator_factory = self.job_orchestrator_factory
40
+ self.__job_orchestrator: Optional[AsyncJobOrchestrator] = None
37
41
  self._parameters = parameters
38
42
 
39
43
  @property
@@ -50,6 +54,17 @@ class AsyncRetriever(Retriever):
50
54
  """
51
55
  pass
52
56
 
57
+ @property
58
+ def _job_orchestrator(self) -> AsyncJobOrchestrator:
59
+ if not self.__job_orchestrator:
60
+ raise AirbyteTracedException(
61
+ message="Invalid state within AsyncJobRetriever. Please contact Airbyte Support",
62
+ internal_message="AsyncPartitionRepository is expected to be accessed only after `stream_slices`",
63
+ failure_type=FailureType.system_error,
64
+ )
65
+
66
+ return self.__job_orchestrator
67
+
53
68
  def _get_stream_state(self) -> StreamState:
54
69
  """
55
70
  Gets the current state of the stream.
@@ -84,7 +99,15 @@ class AsyncRetriever(Retriever):
84
99
  return stream_slice["partition"] # type: ignore # stream_slice["partition"] has been added as an AsyncPartition as part of stream_slices
85
100
 
86
101
  def stream_slices(self) -> Iterable[Optional[StreamSlice]]:
87
- return self.stream_slicer.stream_slices()
102
+ slices = self.stream_slicer.stream_slices()
103
+ self.__job_orchestrator = self._job_orchestrator_factory(slices)
104
+
105
+ for completed_partition in self._job_orchestrator.create_and_get_completed_partitions():
106
+ yield StreamSlice(
107
+ partition=dict(completed_partition.stream_slice.partition)
108
+ | {"partition": completed_partition},
109
+ cursor_slice=completed_partition.stream_slice.cursor_slice,
110
+ )
88
111
 
89
112
  def read_records(
90
113
  self,
@@ -93,7 +116,7 @@ class AsyncRetriever(Retriever):
93
116
  ) -> Iterable[StreamData]:
94
117
  stream_state: StreamState = self._get_stream_state()
95
118
  partition: AsyncPartition = self._validate_and_get_stream_slice_partition(stream_slice)
96
- records: Iterable[Mapping[str, Any]] = self.stream_slicer.fetch_records(partition)
119
+ records: Iterable[Mapping[str, Any]] = self._job_orchestrator.fetch_records(partition)
97
120
 
98
121
  yield from self.record_selector.filter_and_transform(
99
122
  all_data=records,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: airbyte-cdk
3
- Version: 6.11.2.dev1
3
+ Version: 6.12.0rc1
4
4
  Summary: A framework for writing Airbyte Connectors.
5
5
  Home-page: https://airbyte.com
6
6
  License: MIT
@@ -66,15 +66,18 @@ airbyte_cdk/sources/declarative/concurrent_declarative_source.py,sha256=PxP4p268
66
66
  airbyte_cdk/sources/declarative/datetime/__init__.py,sha256=l9LG7Qm6e5r_qgqfVKnx3mXYtg1I9MmMjomVIPfU4XA,177
67
67
  airbyte_cdk/sources/declarative/datetime/datetime_parser.py,sha256=SX9JjdesN1edN2WVUVMzU_ptqp2QB1OnsnjZ4mwcX7w,2579
68
68
  airbyte_cdk/sources/declarative/datetime/min_max_datetime.py,sha256=0BHBtDNQZfvwM45-tY5pNlTcKAFSGGNxemoi0Jic-0E,5785
69
- airbyte_cdk/sources/declarative/declarative_component_schema.yaml,sha256=9DYx7lQ2r4rlHcWG-ClA27NZ1mzjHQyh4ZHSe5wErI8,127973
69
+ airbyte_cdk/sources/declarative/declarative_component_schema.yaml,sha256=aW6LC_YuqlqqCiRgBKm7ecNsF_0iPi1NF8sDmiq6wsA,130106
70
70
  airbyte_cdk/sources/declarative/declarative_source.py,sha256=nF7wBqFd3AQmEKAm4CnIo29CJoQL562cJGSCeL8U8bA,1531
71
71
  airbyte_cdk/sources/declarative/declarative_stream.py,sha256=JRyNeOIpsFu4ztVZsN6sncqUEIqIE-bUkD2TPgbMgk0,10375
72
- airbyte_cdk/sources/declarative/decoders/__init__.py,sha256=hNlhaB5FjNC6IfJyglj5ZJWkYD2nEAukMDmzRz5PC6o,671
72
+ airbyte_cdk/sources/declarative/decoders/__init__.py,sha256=q4XSJFXbVYgXoal910hrCL6t-EQLBtLUq4gvP1eNW9o,773
73
73
  airbyte_cdk/sources/declarative/decoders/decoder.py,sha256=sl-Gt8lXi7yD2Q-sD8je5QS2PbgrgsYjxRLWsay7DMc,826
74
74
  airbyte_cdk/sources/declarative/decoders/json_decoder.py,sha256=qdbjeR6RffKaah_iWvMsOcDolYuxJY5DaI3b9AMTZXg,3327
75
75
  airbyte_cdk/sources/declarative/decoders/noop_decoder.py,sha256=iZh0yKY_JzgBnJWiubEusf5c0o6Khd-8EWFWT-8EgFo,542
76
76
  airbyte_cdk/sources/declarative/decoders/pagination_decoder_decorator.py,sha256=ZVBZhAOl0I0MymXN5CKTC-kIXG4GuUQAEyn0XpUDuSE,1081
77
+ airbyte_cdk/sources/declarative/decoders/parsers/__init__.py,sha256=3qvAJF3O2Ie0qK5ANgsEKR136t7HKk53rR_FyO8ihuY,186
78
+ airbyte_cdk/sources/declarative/decoders/parsers/parsers.py,sha256=Xlz4xmRYAtMFqdvAMwEdTxh-90glKlijMEm6qLOyuAs,1257
77
79
  airbyte_cdk/sources/declarative/decoders/xml_decoder.py,sha256=EU-7t-5vIGRHZ14h-f0GUE4V5-eTM9Flux-A8xgI1Rc,3117
80
+ airbyte_cdk/sources/declarative/decoders/zipfile_decoder.py,sha256=IPLCgYpab6og6j7BdvBuhn_7c1ZYyg8yu48DPkvA84c,1752
78
81
  airbyte_cdk/sources/declarative/exceptions.py,sha256=kTPUA4I2NV4J6HDz-mKPGMrfuc592akJnOyYx38l_QM,176
79
82
  airbyte_cdk/sources/declarative/extractors/__init__.py,sha256=YFuL4D4RuuB8E1DNSbJNIj0_HApOlyECoJ_s8DuJMeI,611
80
83
  airbyte_cdk/sources/declarative/extractors/dpath_extractor.py,sha256=wR4Ol4MG2lt5UlqXF5EU_k7qa5cN4_-luu3PJ1PlO3A,3131
@@ -104,14 +107,13 @@ airbyte_cdk/sources/declarative/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW
104
107
  airbyte_cdk/sources/declarative/migrations/legacy_to_per_partition_state_migration.py,sha256=iemy3fKLczcU0-Aor7tx5jcT6DRedKMqyK7kCOp01hg,3924
105
108
  airbyte_cdk/sources/declarative/migrations/state_migration.py,sha256=KWPjealMLKSMtajXgkdGgKg7EmTLR-CqqD7UIh0-eDU,794
106
109
  airbyte_cdk/sources/declarative/models/__init__.py,sha256=nUFxNCiKeYRVXuZEKA7GD-lTHxsiKcQ8FitZjKhPIvE,100
107
- airbyte_cdk/sources/declarative/models/declarative_component_schema.py,sha256=2T6-9R5O9jMTjL7w1jwjy8SDzJnkrdPl2MsWnKN6GQg,89936
110
+ airbyte_cdk/sources/declarative/models/declarative_component_schema.py,sha256=94efE5chOvaQaBTRx-Hxu2xyN6mDZ7DuFWJUH5fOgWY,91690
108
111
  airbyte_cdk/sources/declarative/parsers/__init__.py,sha256=ZnqYNxHsKCgO38IwB34RQyRMXTs4GTvlRi3ImKnIioo,61
109
112
  airbyte_cdk/sources/declarative/parsers/custom_exceptions.py,sha256=Rir9_z3Kcd5Es0-LChrzk-0qubAsiK_RSEnLmK2OXm8,553
110
113
  airbyte_cdk/sources/declarative/parsers/manifest_component_transformer.py,sha256=CXwTfD3wSQq3okcqwigpprbHhSURUokh4GK2OmOyKC8,9132
111
114
  airbyte_cdk/sources/declarative/parsers/manifest_reference_resolver.py,sha256=IWUOdF03o-aQn0Occo1BJCxU0Pz-QILk5L67nzw2thw,6803
112
- airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py,sha256=Z0i4Sdrv-AcFveaKaL6MnfOzXWC5zNa6AGm1PPKK-x4,104682
113
- airbyte_cdk/sources/declarative/partition_routers/__init__.py,sha256=974SY1RFwitUCiiDHuFHDGmSNu1D72z3bSTpvlBwAho,911
114
- airbyte_cdk/sources/declarative/partition_routers/async_job_partition_router.py,sha256=n82J15S8bjeMZ5uROu--P3hnbQoxkY5v7RPHYx7g7ro,2929
115
+ airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py,sha256=62HI4jMJE7EUJY8GLuGL33mfBmfP7zVSnoLcdyTlwYw,105328
116
+ airbyte_cdk/sources/declarative/partition_routers/__init__.py,sha256=1NjaZoGAIefvWwj6wx-LOKIXXWS-UnBlZFnuR7y6uYA,745
115
117
  airbyte_cdk/sources/declarative/partition_routers/cartesian_product_stream_slicer.py,sha256=c5cuVFM6NFkuQqG8Z5IwkBuwDrvXZN1CunUOM_L0ezg,6892
116
118
  airbyte_cdk/sources/declarative/partition_routers/list_partition_router.py,sha256=t7pRdFWfFWJtQQG19c9PVeMODyO2BknRTakpM5U9N-8,4844
117
119
  airbyte_cdk/sources/declarative/partition_routers/partition_router.py,sha256=YyEIzdmLd1FjbVP3QbQ2VFCLW_P-OGbVh6VpZShp54k,2218
@@ -158,7 +160,7 @@ airbyte_cdk/sources/declarative/resolvers/components_resolver.py,sha256=KPjKc0yb
158
160
  airbyte_cdk/sources/declarative/resolvers/config_components_resolver.py,sha256=dz4iJV9liD_LzY_Mn4XmAStoUll60R3MIGWV4aN3pgg,5223
159
161
  airbyte_cdk/sources/declarative/resolvers/http_components_resolver.py,sha256=ZA2vrHQKfXNMcH3x1iuyFOTGNzYDhUFT2qcaiOzSK0A,4271
160
162
  airbyte_cdk/sources/declarative/retrievers/__init__.py,sha256=FVQpUGVwp2Gibk4gp07VmLKX5AafUlsZWFSrDpUDuJM,443
161
- airbyte_cdk/sources/declarative/retrievers/async_retriever.py,sha256=3jgor7a6_s_9KgqHmPk6cWMDZ-6OugFPjCajIkC3Onw,3721
163
+ airbyte_cdk/sources/declarative/retrievers/async_retriever.py,sha256=WDFnjrXLz3-YEjFhmlMkWAn9AJvnZ0mk9FyC8DAhEYk,4976
162
164
  airbyte_cdk/sources/declarative/retrievers/retriever.py,sha256=XPLs593Xv8c5cKMc37XzUAYmzlXd1a7eSsspM-CMuWA,1696
163
165
  airbyte_cdk/sources/declarative/retrievers/simple_retriever.py,sha256=N4swGw5mfuTXJ2R7AKX18CHzizsr69pXwt5uSHLPi48,24172
164
166
  airbyte_cdk/sources/declarative/schema/__init__.py,sha256=Io9vninzlEjQ2uFmWklxfwNM0cXfljtzOz5zL1OVyT4,701
@@ -337,8 +339,8 @@ airbyte_cdk/utils/slice_hasher.py,sha256=-pHexlNYoWYPnXNH-M7HEbjmeJe9Zk7SJijdQ7d
337
339
  airbyte_cdk/utils/spec_schema_transformations.py,sha256=-5HTuNsnDBAhj-oLeQXwpTGA0HdcjFOf2zTEMUTTg_Y,816
338
340
  airbyte_cdk/utils/stream_status_utils.py,sha256=ZmBoiy5HVbUEHAMrUONxZvxnvfV9CesmQJLDTAIWnWw,1171
339
341
  airbyte_cdk/utils/traced_exception.py,sha256=C8uIBuCL_E4WnBAOPSxBicD06JAldoN9fGsQDp463OY,6292
340
- airbyte_cdk-6.11.2.dev1.dist-info/LICENSE.txt,sha256=Wfe61S4BaGPj404v8lrAbvhjYR68SHlkzeYrg3_bbuM,1051
341
- airbyte_cdk-6.11.2.dev1.dist-info/METADATA,sha256=WrA1bFbcp_mLbP53VO8SKGP4-aP-a5mALs0l3fNQJaA,5955
342
- airbyte_cdk-6.11.2.dev1.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
343
- airbyte_cdk-6.11.2.dev1.dist-info/entry_points.txt,sha256=fj-e3PAQvsxsQzyyq8UkG1k8spunWnD4BAH2AwlR6NM,95
344
- airbyte_cdk-6.11.2.dev1.dist-info/RECORD,,
342
+ airbyte_cdk-6.12.0rc1.dist-info/LICENSE.txt,sha256=Wfe61S4BaGPj404v8lrAbvhjYR68SHlkzeYrg3_bbuM,1051
343
+ airbyte_cdk-6.12.0rc1.dist-info/METADATA,sha256=Dmtuhf6DiAt2U3kmIQjlVuruZToq8QNPhsqtZvUePAE,5953
344
+ airbyte_cdk-6.12.0rc1.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
345
+ airbyte_cdk-6.12.0rc1.dist-info/entry_points.txt,sha256=fj-e3PAQvsxsQzyyq8UkG1k8spunWnD4BAH2AwlR6NM,95
346
+ airbyte_cdk-6.12.0rc1.dist-info/RECORD,,
@@ -1,65 +0,0 @@
1
- # Copyright (c) 2024 Airbyte, Inc., all rights reserved.
2
-
3
- from dataclasses import InitVar, dataclass, field
4
- from typing import Any, Callable, Iterable, Mapping, Optional
5
-
6
- from airbyte_cdk.models import FailureType
7
- from airbyte_cdk.sources.declarative.async_job.job_orchestrator import (
8
- AsyncJobOrchestrator,
9
- AsyncPartition,
10
- )
11
- from airbyte_cdk.sources.declarative.partition_routers.single_partition_router import (
12
- SinglePartitionRouter,
13
- )
14
- from airbyte_cdk.sources.streams.concurrent.partitions.stream_slicer import StreamSlicer
15
- from airbyte_cdk.sources.types import Config, StreamSlice
16
- from airbyte_cdk.utils.traced_exception import AirbyteTracedException
17
-
18
-
19
- @dataclass
20
- class AsyncJobPartitionRouter(StreamSlicer):
21
- """
22
- Partition router that creates async jobs in a source API, periodically polls for job
23
- completion, and supplies the completed job URL locations as stream slices so that
24
- records can be extracted.
25
- """
26
-
27
- config: Config
28
- parameters: InitVar[Mapping[str, Any]]
29
- job_orchestrator_factory: Callable[[Iterable[StreamSlice]], AsyncJobOrchestrator]
30
- stream_slicer: StreamSlicer = field(
31
- default_factory=lambda: SinglePartitionRouter(parameters={})
32
- )
33
-
34
- def __post_init__(self, parameters: Mapping[str, Any]) -> None:
35
- self._job_orchestrator_factory = self.job_orchestrator_factory
36
- self._job_orchestrator: Optional[AsyncJobOrchestrator] = None
37
- self._parameters = parameters
38
-
39
- def stream_slices(self) -> Iterable[StreamSlice]:
40
- slices = self.stream_slicer.stream_slices()
41
- self._job_orchestrator = self._job_orchestrator_factory(slices)
42
-
43
- for completed_partition in self._job_orchestrator.create_and_get_completed_partitions():
44
- yield StreamSlice(
45
- partition=dict(completed_partition.stream_slice.partition)
46
- | {"partition": completed_partition},
47
- cursor_slice=completed_partition.stream_slice.cursor_slice,
48
- )
49
-
50
- def fetch_records(self, partition: AsyncPartition) -> Iterable[Mapping[str, Any]]:
51
- """
52
- This method of fetching records extends beyond what a PartitionRouter/StreamSlicer should
53
- be responsible for. However, this was added in because the JobOrchestrator is required to
54
- retrieve records. And without defining fetch_records() on this class, we're stuck with either
55
- passing the JobOrchestrator to the AsyncRetriever or storing it on multiple classes.
56
- """
57
-
58
- if not self._job_orchestrator:
59
- raise AirbyteTracedException(
60
- message="Invalid state within AsyncJobRetriever. Please contact Airbyte Support",
61
- internal_message="AsyncPartitionRepository is expected to be accessed only after `stream_slices`",
62
- failure_type=FailureType.system_error,
63
- )
64
-
65
- return self._job_orchestrator.fetch_records(partition=partition)