airbyte-cdk 6.13.1.dev4109__py3-none-any.whl → 6.14.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- airbyte_cdk/entrypoint.py +1 -13
- airbyte_cdk/sources/declarative/auth/oauth.py +0 -26
- airbyte_cdk/sources/declarative/concurrent_declarative_source.py +51 -24
- airbyte_cdk/sources/declarative/declarative_component_schema.yaml +20 -128
- airbyte_cdk/sources/declarative/extractors/__init__.py +0 -2
- airbyte_cdk/sources/declarative/extractors/record_selector.py +7 -5
- airbyte_cdk/sources/declarative/models/declarative_component_schema.py +11 -97
- airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py +14 -71
- airbyte_cdk/sources/declarative/requesters/http_job_repository.py +4 -33
- airbyte_cdk/sources/declarative/requesters/paginators/default_paginator.py +35 -52
- airbyte_cdk/sources/declarative/requesters/paginators/no_pagination.py +7 -10
- airbyte_cdk/sources/declarative/requesters/paginators/paginator.py +4 -9
- airbyte_cdk/sources/declarative/requesters/paginators/strategies/cursor_pagination_strategy.py +6 -11
- airbyte_cdk/sources/declarative/requesters/paginators/strategies/offset_increment.py +13 -13
- airbyte_cdk/sources/declarative/requesters/paginators/strategies/page_increment.py +13 -14
- airbyte_cdk/sources/declarative/requesters/paginators/strategies/pagination_strategy.py +7 -6
- airbyte_cdk/sources/declarative/requesters/paginators/strategies/stop_condition.py +10 -10
- airbyte_cdk/sources/declarative/retrievers/async_retriever.py +4 -1
- airbyte_cdk/sources/declarative/retrievers/simple_retriever.py +64 -71
- airbyte_cdk/sources/declarative/stream_slicers/declarative_partition_generator.py +4 -4
- airbyte_cdk/sources/declarative/transformations/flatten_fields.py +1 -3
- airbyte_cdk/sources/file_based/config/abstract_file_based_spec.py +0 -11
- airbyte_cdk/sources/file_based/exceptions.py +0 -34
- airbyte_cdk/sources/file_based/file_based_source.py +5 -28
- airbyte_cdk/sources/file_based/file_based_stream_reader.py +4 -18
- airbyte_cdk/sources/file_based/file_types/unstructured_parser.py +2 -25
- airbyte_cdk/sources/file_based/stream/default_file_based_stream.py +2 -30
- airbyte_cdk/sources/streams/http/requests_native_auth/abstract_oauth.py +4 -20
- airbyte_cdk/sources/streams/http/requests_native_auth/oauth.py +4 -34
- airbyte_cdk/sources/types.py +0 -3
- {airbyte_cdk-6.13.1.dev4109.dist-info → airbyte_cdk-6.14.0.dist-info}/METADATA +2 -2
- {airbyte_cdk-6.13.1.dev4109.dist-info → airbyte_cdk-6.14.0.dist-info}/RECORD +35 -38
- {airbyte_cdk-6.13.1.dev4109.dist-info → airbyte_cdk-6.14.0.dist-info}/WHEEL +1 -1
- airbyte_cdk/sources/declarative/extractors/type_transformer.py +0 -55
- airbyte_cdk/sources/declarative/requesters/README.md +0 -57
- airbyte_cdk/sources/declarative/transformations/keys_replace_transformation.py +0 -61
- {airbyte_cdk-6.13.1.dev4109.dist-info → airbyte_cdk-6.14.0.dist-info}/LICENSE.txt +0 -0
- {airbyte_cdk-6.13.1.dev4109.dist-info → airbyte_cdk-6.14.0.dist-info}/entry_points.txt +0 -0
@@ -268,22 +268,6 @@ class CustomSchemaLoader(BaseModel):
|
|
268
268
|
parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
|
269
269
|
|
270
270
|
|
271
|
-
class CustomSchemaNormalization(BaseModel):
|
272
|
-
class Config:
|
273
|
-
extra = Extra.allow
|
274
|
-
|
275
|
-
type: Literal["CustomSchemaNormalization"]
|
276
|
-
class_name: str = Field(
|
277
|
-
...,
|
278
|
-
description="Fully-qualified name of the class that will be implementing the custom normalization. The format is `source_<name>.<package>.<class_name>`.",
|
279
|
-
examples=[
|
280
|
-
"source_amazon_seller_partner.components.LedgerDetailedViewReportsTypeTransformer"
|
281
|
-
],
|
282
|
-
title="Class Name",
|
283
|
-
)
|
284
|
-
parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
|
285
|
-
|
286
|
-
|
287
271
|
class CustomStateMigration(BaseModel):
|
288
272
|
class Config:
|
289
273
|
extra = Extra.allow
|
@@ -481,24 +465,12 @@ class RefreshTokenUpdater(BaseModel):
|
|
481
465
|
|
482
466
|
class OAuthAuthenticator(BaseModel):
|
483
467
|
type: Literal["OAuthAuthenticator"]
|
484
|
-
client_id_name: Optional[str] = Field(
|
485
|
-
"client_id",
|
486
|
-
description="The name of the property to use to refresh the `access_token`.",
|
487
|
-
examples=["custom_app_id"],
|
488
|
-
title="Client ID Property Name",
|
489
|
-
)
|
490
468
|
client_id: str = Field(
|
491
469
|
...,
|
492
470
|
description="The OAuth client ID. Fill it in the user inputs.",
|
493
471
|
examples=["{{ config['client_id }}", "{{ config['credentials']['client_id }}"],
|
494
472
|
title="Client ID",
|
495
473
|
)
|
496
|
-
client_secret_name: Optional[str] = Field(
|
497
|
-
"client_secret",
|
498
|
-
description="The name of the property to use to refresh the `access_token`.",
|
499
|
-
examples=["custom_app_secret"],
|
500
|
-
title="Client Secret Property Name",
|
501
|
-
)
|
502
474
|
client_secret: str = Field(
|
503
475
|
...,
|
504
476
|
description="The OAuth client secret. Fill it in the user inputs.",
|
@@ -508,12 +480,6 @@ class OAuthAuthenticator(BaseModel):
|
|
508
480
|
],
|
509
481
|
title="Client Secret",
|
510
482
|
)
|
511
|
-
refresh_token_name: Optional[str] = Field(
|
512
|
-
"refresh_token",
|
513
|
-
description="The name of the property to use to refresh the `access_token`.",
|
514
|
-
examples=["custom_app_refresh_value"],
|
515
|
-
title="Refresh Token Property Name",
|
516
|
-
)
|
517
483
|
refresh_token: Optional[str] = Field(
|
518
484
|
None,
|
519
485
|
description="Credential artifact used to get a new access token.",
|
@@ -547,12 +513,6 @@ class OAuthAuthenticator(BaseModel):
|
|
547
513
|
examples=["expires_in"],
|
548
514
|
title="Token Expiry Property Name",
|
549
515
|
)
|
550
|
-
grant_type_name: Optional[str] = Field(
|
551
|
-
"grant_type",
|
552
|
-
description="The name of the property to use to refresh the `access_token`.",
|
553
|
-
examples=["custom_grant_type"],
|
554
|
-
title="Grant Type Property Name",
|
555
|
-
)
|
556
516
|
grant_type: Optional[str] = Field(
|
557
517
|
"refresh_token",
|
558
518
|
description="Specifies the OAuth2 grant type. If set to refresh_token, the refresh_token needs to be provided as well. For client_credentials, only client id and secret are required. Other grant types are not officially supported.",
|
@@ -763,38 +723,6 @@ class KeysToSnakeCase(BaseModel):
|
|
763
723
|
|
764
724
|
class FlattenFields(BaseModel):
|
765
725
|
type: Literal["FlattenFields"]
|
766
|
-
flatten_lists: Optional[bool] = Field(
|
767
|
-
True,
|
768
|
-
description="Whether to flatten lists or leave it as is. Default is True.",
|
769
|
-
title="Flatten Lists",
|
770
|
-
)
|
771
|
-
parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
|
772
|
-
|
773
|
-
|
774
|
-
class KeysReplace(BaseModel):
|
775
|
-
type: Literal["KeysReplace"]
|
776
|
-
old: str = Field(
|
777
|
-
...,
|
778
|
-
description="Old value to replace.",
|
779
|
-
examples=[
|
780
|
-
" ",
|
781
|
-
"{{ record.id }}",
|
782
|
-
"{{ config['id'] }}",
|
783
|
-
"{{ stream_slice['id'] }}",
|
784
|
-
],
|
785
|
-
title="Old value",
|
786
|
-
)
|
787
|
-
new: str = Field(
|
788
|
-
...,
|
789
|
-
description="New value to set.",
|
790
|
-
examples=[
|
791
|
-
"_",
|
792
|
-
"{{ record.id }}",
|
793
|
-
"{{ config['id'] }}",
|
794
|
-
"{{ stream_slice['id'] }}",
|
795
|
-
],
|
796
|
-
title="New value",
|
797
|
-
)
|
798
726
|
parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
|
799
727
|
|
800
728
|
|
@@ -883,8 +811,8 @@ class OauthConnectorInputSpecification(BaseModel):
|
|
883
811
|
...,
|
884
812
|
description="The DeclarativeOAuth Specific string URL string template to initiate the authentication.\nThe placeholders are replaced during the processing to provide neccessary values.",
|
885
813
|
examples=[
|
886
|
-
"https://domain.host.com/marketing_api/auth?{
|
887
|
-
"https://endpoint.host.com/oauth2/authorize?{
|
814
|
+
"https://domain.host.com/marketing_api/auth?{client_id_key}={{client_id_key}}&{redirect_uri_key}={urlEncoder:{{redirect_uri_key}}}&{state_key}={{state_key}}",
|
815
|
+
"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}",
|
888
816
|
],
|
889
817
|
title="Consent URL",
|
890
818
|
)
|
@@ -898,18 +826,14 @@ class OauthConnectorInputSpecification(BaseModel):
|
|
898
826
|
...,
|
899
827
|
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.",
|
900
828
|
examples=[
|
901
|
-
"https://auth.host.com/oauth2/token?{
|
829
|
+
"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}}}"
|
902
830
|
],
|
903
831
|
title="Access Token URL",
|
904
832
|
)
|
905
833
|
access_token_headers: Optional[Dict[str, Any]] = Field(
|
906
834
|
None,
|
907
835
|
description="The DeclarativeOAuth Specific optional headers to inject while exchanging the `auth_code` to `access_token` during `completeOAuthFlow` step.",
|
908
|
-
examples=[
|
909
|
-
{
|
910
|
-
"Authorization": "Basic {{ {{ client_id_value }}:{{ client_secret_value }} | base64Encoder }}"
|
911
|
-
}
|
912
|
-
],
|
836
|
+
examples=[{"Authorization": "Basic {base64Encoder:{client_id}:{client_secret}}"}],
|
913
837
|
title="Access Token Headers",
|
914
838
|
)
|
915
839
|
access_token_params: Optional[Dict[str, Any]] = Field(
|
@@ -917,15 +841,15 @@ class OauthConnectorInputSpecification(BaseModel):
|
|
917
841
|
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.",
|
918
842
|
examples=[
|
919
843
|
{
|
920
|
-
"{
|
921
|
-
"{
|
922
|
-
"{
|
844
|
+
"{auth_code_key}": "{{auth_code_key}}",
|
845
|
+
"{client_id_key}": "{{client_id_key}}",
|
846
|
+
"{client_secret_key}": "{{client_secret_key}}",
|
923
847
|
}
|
924
848
|
],
|
925
849
|
title="Access Token Query Params (Json Encoded)",
|
926
850
|
)
|
927
|
-
extract_output:
|
928
|
-
|
851
|
+
extract_output: List[str] = Field(
|
852
|
+
...,
|
929
853
|
description="The DeclarativeOAuth Specific list of strings to indicate which keys should be extracted and returned back to the input config.",
|
930
854
|
examples=[["access_token", "refresh_token", "other_field"]],
|
931
855
|
title="Extract Output",
|
@@ -994,7 +918,7 @@ class OAuthConfigSpecification(BaseModel):
|
|
994
918
|
)
|
995
919
|
oauth_connector_input_specification: Optional[OauthConnectorInputSpecification] = Field(
|
996
920
|
None,
|
997
|
-
description='The DeclarativeOAuth specific blob.\nPertains to the fields defined by the connector relating to the OAuth flow.\n\nInterpolation capabilities:\n- The variables placeholders are declared as `{
|
921
|
+
description='The DeclarativeOAuth specific blob.\nPertains to the fields defined by the connector relating to the OAuth flow.\n\nInterpolation capabilities:\n- The variables placeholders are declared as `{my_var}`.\n- The nested resolution variables like `{{my_nested_var}}` is allowed as well.\n\n- The allowed interpolation context is:\n + base64Encoder - encode to `base64`, {base64Encoder:{my_var_a}:{my_var_b}}\n + base64Decorer - decode from `base64` encoded string, {base64Decoder:{my_string_variable_or_string_value}}\n + urlEncoder - encode the input string to URL-like format, {urlEncoder:https://test.host.com/endpoint}\n + urlDecorer - decode the input url-encoded string into text format, {urlDecoder:https%3A%2F%2Fairbyte.io}\n + codeChallengeS256 - get the `codeChallenge` encoded value to provide additional data-provider specific authorisation values, {codeChallengeS256:{state_value}}\n\nExamples:\n - The TikTok Marketing DeclarativeOAuth spec:\n {\n "oauth_connector_input_specification": {\n "type": "object",\n "additionalProperties": false,\n "properties": {\n "consent_url": "https://ads.tiktok.com/marketing_api/auth?{client_id_key}={{client_id_key}}&{redirect_uri_key}={urlEncoder:{{redirect_uri_key}}}&{state_key}={{state_key}}",\n "access_token_url": "https://business-api.tiktok.com/open_api/v1.3/oauth2/access_token/",\n "access_token_params": {\n "{auth_code_key}": "{{auth_code_key}}",\n "{client_id_key}": "{{client_id_key}}",\n "{client_secret_key}": "{{client_secret_key}}"\n },\n "access_token_headers": {\n "Content-Type": "application/json",\n "Accept": "application/json"\n },\n "extract_output": ["data.access_token"],\n "client_id_key": "app_id",\n "client_secret_key": "secret",\n "auth_code_key": "auth_code"\n }\n }\n }',
|
998
922
|
title="DeclarativeOAuth Connector Specification",
|
999
923
|
)
|
1000
924
|
complete_oauth_output_specification: Optional[Dict[str, Any]] = Field(
|
@@ -1589,11 +1513,7 @@ class RecordSelector(BaseModel):
|
|
1589
1513
|
description="Responsible for filtering records to be emitted by the Source.",
|
1590
1514
|
title="Record Filter",
|
1591
1515
|
)
|
1592
|
-
schema_normalization: Optional[
|
1593
|
-
SchemaNormalization.None_,
|
1594
|
-
description="Responsible for normalization according to the schema.",
|
1595
|
-
title="Schema Normalization",
|
1596
|
-
)
|
1516
|
+
schema_normalization: Optional[SchemaNormalization] = SchemaNormalization.None_
|
1597
1517
|
parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters")
|
1598
1518
|
|
1599
1519
|
|
@@ -1781,7 +1701,6 @@ class DeclarativeStream(BaseModel):
|
|
1781
1701
|
KeysToLower,
|
1782
1702
|
KeysToSnakeCase,
|
1783
1703
|
FlattenFields,
|
1784
|
-
KeysReplace,
|
1785
1704
|
]
|
1786
1705
|
]
|
1787
1706
|
] = Field(
|
@@ -1956,7 +1875,6 @@ class DynamicSchemaLoader(BaseModel):
|
|
1956
1875
|
KeysToLower,
|
1957
1876
|
KeysToSnakeCase,
|
1958
1877
|
FlattenFields,
|
1959
|
-
KeysReplace,
|
1960
1878
|
]
|
1961
1879
|
]
|
1962
1880
|
] = Field(
|
@@ -2078,10 +1996,6 @@ class AsyncRetriever(BaseModel):
|
|
2078
1996
|
...,
|
2079
1997
|
description="Requester component that describes how to prepare HTTP requests to send to the source API to fetch the status of the running async job.",
|
2080
1998
|
)
|
2081
|
-
url_requester: Optional[Union[CustomRequester, HttpRequester]] = Field(
|
2082
|
-
None,
|
2083
|
-
description="Requester component that describes how to prepare HTTP requests to send to the source API to extract the url from polling response by the completed async job.",
|
2084
|
-
)
|
2085
1999
|
download_requester: Union[CustomRequester, HttpRequester] = Field(
|
2086
2000
|
...,
|
2087
2001
|
description="Requester component that describes how to prepare HTTP requests to send to the source API to download the data provided by the completed async job.",
|
@@ -82,6 +82,9 @@ from airbyte_cdk.sources.declarative.extractors import (
|
|
82
82
|
from airbyte_cdk.sources.declarative.extractors.record_filter import (
|
83
83
|
ClientSideIncrementalRecordFilterDecorator,
|
84
84
|
)
|
85
|
+
from airbyte_cdk.sources.declarative.extractors.record_selector import (
|
86
|
+
SCHEMA_TRANSFORMER_TYPE_MAPPING,
|
87
|
+
)
|
85
88
|
from airbyte_cdk.sources.declarative.incremental import (
|
86
89
|
ChildPartitionResumableFullRefreshCursor,
|
87
90
|
CursorFactory,
|
@@ -97,9 +100,7 @@ from airbyte_cdk.sources.declarative.interpolation.interpolated_mapping import I
|
|
97
100
|
from airbyte_cdk.sources.declarative.migrations.legacy_to_per_partition_state_migration import (
|
98
101
|
LegacyToPerPartitionStateMigration,
|
99
102
|
)
|
100
|
-
from airbyte_cdk.sources.declarative.models import
|
101
|
-
CustomStateMigration,
|
102
|
-
)
|
103
|
+
from airbyte_cdk.sources.declarative.models import CustomStateMigration
|
103
104
|
from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
|
104
105
|
AddedFieldDefinition as AddedFieldDefinitionModel,
|
105
106
|
)
|
@@ -184,9 +185,6 @@ from airbyte_cdk.sources.declarative.models.declarative_component_schema import
|
|
184
185
|
from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
|
185
186
|
CustomSchemaLoader as CustomSchemaLoader,
|
186
187
|
)
|
187
|
-
from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
|
188
|
-
CustomSchemaNormalization as CustomSchemaNormalizationModel,
|
189
|
-
)
|
190
188
|
from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
|
191
189
|
CustomTransformation as CustomTransformationModel,
|
192
190
|
)
|
@@ -256,9 +254,6 @@ from airbyte_cdk.sources.declarative.models.declarative_component_schema import
|
|
256
254
|
from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
|
257
255
|
JwtPayload as JwtPayloadModel,
|
258
256
|
)
|
259
|
-
from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
|
260
|
-
KeysReplace as KeysReplaceModel,
|
261
|
-
)
|
262
257
|
from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
|
263
258
|
KeysToLower as KeysToLowerModel,
|
264
259
|
)
|
@@ -313,9 +308,6 @@ from airbyte_cdk.sources.declarative.models.declarative_component_schema import
|
|
313
308
|
from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
|
314
309
|
ResponseToFileExtractor as ResponseToFileExtractorModel,
|
315
310
|
)
|
316
|
-
from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
|
317
|
-
SchemaNormalization as SchemaNormalizationModel,
|
318
|
-
)
|
319
311
|
from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
|
320
312
|
SchemaTypeIdentifier as SchemaTypeIdentifierModel,
|
321
313
|
)
|
@@ -425,9 +417,6 @@ from airbyte_cdk.sources.declarative.transformations.add_fields import AddedFiel
|
|
425
417
|
from airbyte_cdk.sources.declarative.transformations.flatten_fields import (
|
426
418
|
FlattenFields,
|
427
419
|
)
|
428
|
-
from airbyte_cdk.sources.declarative.transformations.keys_replace_transformation import (
|
429
|
-
KeysReplaceTransformation,
|
430
|
-
)
|
431
420
|
from airbyte_cdk.sources.declarative.transformations.keys_to_lower_transformation import (
|
432
421
|
KeysToLowerTransformation,
|
433
422
|
)
|
@@ -450,11 +439,6 @@ from airbyte_cdk.sources.utils.transform import TransformConfig, TypeTransformer
|
|
450
439
|
|
451
440
|
ComponentDefinition = Mapping[str, Any]
|
452
441
|
|
453
|
-
SCHEMA_TRANSFORMER_TYPE_MAPPING = {
|
454
|
-
SchemaNormalizationModel.None_: TransformConfig.NoTransform,
|
455
|
-
SchemaNormalizationModel.Default: TransformConfig.DefaultSchemaNormalization,
|
456
|
-
}
|
457
|
-
|
458
442
|
|
459
443
|
class ModelToComponentFactory:
|
460
444
|
EPOCH_DATETIME_FORMAT = "%s"
|
@@ -503,7 +487,6 @@ class ModelToComponentFactory:
|
|
503
487
|
CustomRequesterModel: self.create_custom_component,
|
504
488
|
CustomRetrieverModel: self.create_custom_component,
|
505
489
|
CustomSchemaLoader: self.create_custom_component,
|
506
|
-
CustomSchemaNormalizationModel: self.create_custom_component,
|
507
490
|
CustomStateMigration: self.create_custom_component,
|
508
491
|
CustomPaginationStrategyModel: self.create_custom_component,
|
509
492
|
CustomPartitionRouterModel: self.create_custom_component,
|
@@ -526,7 +509,6 @@ class ModelToComponentFactory:
|
|
526
509
|
GzipParserModel: self.create_gzip_parser,
|
527
510
|
KeysToLowerModel: self.create_keys_to_lower_transformation,
|
528
511
|
KeysToSnakeCaseModel: self.create_keys_to_snake_transformation,
|
529
|
-
KeysReplaceModel: self.create_keys_replace_transformation,
|
530
512
|
FlattenFieldsModel: self.create_flatten_fields,
|
531
513
|
IterableDecoderModel: self.create_iterable_decoder,
|
532
514
|
XmlDecoderModel: self.create_xml_decoder,
|
@@ -648,19 +630,10 @@ class ModelToComponentFactory:
|
|
648
630
|
) -> KeysToSnakeCaseTransformation:
|
649
631
|
return KeysToSnakeCaseTransformation()
|
650
632
|
|
651
|
-
def create_keys_replace_transformation(
|
652
|
-
self, model: KeysReplaceModel, config: Config, **kwargs: Any
|
653
|
-
) -> KeysReplaceTransformation:
|
654
|
-
return KeysReplaceTransformation(
|
655
|
-
old=model.old, new=model.new, parameters=model.parameters or {}
|
656
|
-
)
|
657
|
-
|
658
633
|
def create_flatten_fields(
|
659
634
|
self, model: FlattenFieldsModel, config: Config, **kwargs: Any
|
660
635
|
) -> FlattenFields:
|
661
|
-
return FlattenFields(
|
662
|
-
flatten_lists=model.flatten_lists if model.flatten_lists is not None else True
|
663
|
-
)
|
636
|
+
return FlattenFields()
|
664
637
|
|
665
638
|
@staticmethod
|
666
639
|
def _json_schema_type_name_to_type(value_type: Optional[ValueType]) -> Optional[Type[Any]]:
|
@@ -1587,12 +1560,7 @@ class ModelToComponentFactory:
|
|
1587
1560
|
)
|
1588
1561
|
|
1589
1562
|
def create_http_requester(
|
1590
|
-
self,
|
1591
|
-
model: HttpRequesterModel,
|
1592
|
-
config: Config,
|
1593
|
-
decoder: Decoder = JsonDecoder(parameters={}),
|
1594
|
-
*,
|
1595
|
-
name: str,
|
1563
|
+
self, model: HttpRequesterModel, decoder: Decoder, config: Config, *, name: str
|
1596
1564
|
) -> HttpRequester:
|
1597
1565
|
authenticator = (
|
1598
1566
|
self._create_component_from_model(
|
@@ -1885,24 +1853,15 @@ class ModelToComponentFactory:
|
|
1885
1853
|
expires_in_name=InterpolatedString.create(
|
1886
1854
|
model.expires_in_name or "expires_in", parameters=model.parameters or {}
|
1887
1855
|
).eval(config),
|
1888
|
-
client_id_name=InterpolatedString.create(
|
1889
|
-
model.client_id_name or "client_id", parameters=model.parameters or {}
|
1890
|
-
).eval(config),
|
1891
1856
|
client_id=InterpolatedString.create(
|
1892
1857
|
model.client_id, parameters=model.parameters or {}
|
1893
1858
|
).eval(config),
|
1894
|
-
client_secret_name=InterpolatedString.create(
|
1895
|
-
model.client_secret_name or "client_secret", parameters=model.parameters or {}
|
1896
|
-
).eval(config),
|
1897
1859
|
client_secret=InterpolatedString.create(
|
1898
1860
|
model.client_secret, parameters=model.parameters or {}
|
1899
1861
|
).eval(config),
|
1900
1862
|
access_token_config_path=model.refresh_token_updater.access_token_config_path,
|
1901
1863
|
refresh_token_config_path=model.refresh_token_updater.refresh_token_config_path,
|
1902
1864
|
token_expiry_date_config_path=model.refresh_token_updater.token_expiry_date_config_path,
|
1903
|
-
grant_type_name=InterpolatedString.create(
|
1904
|
-
model.grant_type_name or "grant_type", parameters=model.parameters or {}
|
1905
|
-
).eval(config),
|
1906
1865
|
grant_type=InterpolatedString.create(
|
1907
1866
|
model.grant_type or "refresh_token", parameters=model.parameters or {}
|
1908
1867
|
).eval(config),
|
@@ -1920,15 +1879,11 @@ class ModelToComponentFactory:
|
|
1920
1879
|
return DeclarativeOauth2Authenticator( # type: ignore
|
1921
1880
|
access_token_name=model.access_token_name or "access_token",
|
1922
1881
|
access_token_value=model.access_token_value,
|
1923
|
-
client_id_name=model.client_id_name or "client_id",
|
1924
1882
|
client_id=model.client_id,
|
1925
|
-
client_secret_name=model.client_secret_name or "client_secret",
|
1926
1883
|
client_secret=model.client_secret,
|
1927
1884
|
expires_in_name=model.expires_in_name or "expires_in",
|
1928
|
-
grant_type_name=model.grant_type_name or "grant_type",
|
1929
1885
|
grant_type=model.grant_type or "refresh_token",
|
1930
1886
|
refresh_request_body=model.refresh_request_body,
|
1931
|
-
refresh_token_name=model.refresh_token_name or "refresh_token",
|
1932
1887
|
refresh_token=model.refresh_token,
|
1933
1888
|
scopes=model.scopes,
|
1934
1889
|
token_expiry_date=model.token_expiry_date,
|
@@ -2021,11 +1976,12 @@ class ModelToComponentFactory:
|
|
2021
1976
|
config: Config,
|
2022
1977
|
*,
|
2023
1978
|
name: str,
|
2024
|
-
transformations: List[RecordTransformation]
|
2025
|
-
decoder: Decoder
|
2026
|
-
client_side_incremental_sync: Dict[str, Any]
|
1979
|
+
transformations: List[RecordTransformation],
|
1980
|
+
decoder: Optional[Decoder] = None,
|
1981
|
+
client_side_incremental_sync: Optional[Dict[str, Any]] = None,
|
2027
1982
|
**kwargs: Any,
|
2028
1983
|
) -> RecordSelector:
|
1984
|
+
assert model.schema_normalization is not None # for mypy
|
2029
1985
|
extractor = self._create_component_from_model(
|
2030
1986
|
model=model.extractor, decoder=decoder, config=config
|
2031
1987
|
)
|
@@ -2043,10 +1999,8 @@ class ModelToComponentFactory:
|
|
2043
1999
|
else None,
|
2044
2000
|
**client_side_incremental_sync,
|
2045
2001
|
)
|
2046
|
-
schema_normalization = (
|
2047
|
-
|
2048
|
-
if isinstance(model.schema_normalization, SchemaNormalizationModel)
|
2049
|
-
else self._create_component_from_model(model.schema_normalization, config=config) # type: ignore[arg-type] # custom normalization model expected here
|
2002
|
+
schema_normalization = TypeTransformer(
|
2003
|
+
SCHEMA_TRANSFORMER_TYPE_MAPPING[model.schema_normalization]
|
2050
2004
|
)
|
2051
2005
|
|
2052
2006
|
return RecordSelector(
|
@@ -2054,7 +2008,7 @@ class ModelToComponentFactory:
|
|
2054
2008
|
name=name,
|
2055
2009
|
config=config,
|
2056
2010
|
record_filter=record_filter,
|
2057
|
-
transformations=transformations
|
2011
|
+
transformations=transformations,
|
2058
2012
|
schema_normalization=schema_normalization,
|
2059
2013
|
parameters=model.parameters or {},
|
2060
2014
|
)
|
@@ -2300,7 +2254,7 @@ class ModelToComponentFactory:
|
|
2300
2254
|
extractor=download_extractor,
|
2301
2255
|
name=name,
|
2302
2256
|
record_filter=None,
|
2303
|
-
transformations=
|
2257
|
+
transformations=[],
|
2304
2258
|
schema_normalization=TypeTransformer(TransformConfig.NoTransform),
|
2305
2259
|
config=config,
|
2306
2260
|
parameters={},
|
@@ -2337,16 +2291,6 @@ class ModelToComponentFactory:
|
|
2337
2291
|
if model.delete_requester
|
2338
2292
|
else None
|
2339
2293
|
)
|
2340
|
-
url_requester = (
|
2341
|
-
self._create_component_from_model(
|
2342
|
-
model=model.url_requester,
|
2343
|
-
decoder=decoder,
|
2344
|
-
config=config,
|
2345
|
-
name=f"job extract_url - {name}",
|
2346
|
-
)
|
2347
|
-
if model.url_requester
|
2348
|
-
else None
|
2349
|
-
)
|
2350
2294
|
status_extractor = self._create_component_from_model(
|
2351
2295
|
model=model.status_extractor, decoder=decoder, config=config, name=name
|
2352
2296
|
)
|
@@ -2357,7 +2301,6 @@ class ModelToComponentFactory:
|
|
2357
2301
|
creation_requester=creation_requester,
|
2358
2302
|
polling_requester=polling_requester,
|
2359
2303
|
download_retriever=download_retriever,
|
2360
|
-
url_requester=url_requester,
|
2361
2304
|
abort_requester=abort_requester,
|
2362
2305
|
delete_requester=delete_requester,
|
2363
2306
|
status_extractor=status_extractor,
|
@@ -31,10 +31,6 @@ LOGGER = logging.getLogger("airbyte")
|
|
31
31
|
|
32
32
|
@dataclass
|
33
33
|
class AsyncHttpJobRepository(AsyncJobRepository):
|
34
|
-
"""
|
35
|
-
See Readme file for more details about flow.
|
36
|
-
"""
|
37
|
-
|
38
34
|
creation_requester: Requester
|
39
35
|
polling_requester: Requester
|
40
36
|
download_retriever: SimpleRetriever
|
@@ -48,9 +44,6 @@ class AsyncHttpJobRepository(AsyncJobRepository):
|
|
48
44
|
record_extractor: RecordExtractor = field(
|
49
45
|
init=False, repr=False, default_factory=lambda: ResponseToFileExtractor({})
|
50
46
|
)
|
51
|
-
url_requester: Optional[Requester] = (
|
52
|
-
None # use it in case polling_requester provides some <id> and extra request is needed to obtain list of urls to download from
|
53
|
-
)
|
54
47
|
|
55
48
|
def __post_init__(self) -> None:
|
56
49
|
self._create_job_response_by_id: Dict[str, Response] = {}
|
@@ -193,13 +186,10 @@ class AsyncHttpJobRepository(AsyncJobRepository):
|
|
193
186
|
|
194
187
|
"""
|
195
188
|
|
196
|
-
for url in self.
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
cursor_slice=job_slice.cursor_slice,
|
201
|
-
extra_fields={**job_slice.extra_fields, "url": url},
|
202
|
-
)
|
189
|
+
for url in self.urls_extractor.extract_records(
|
190
|
+
self._polling_job_response_by_id[job.api_job_id()]
|
191
|
+
):
|
192
|
+
stream_slice: StreamSlice = StreamSlice(partition={"url": url}, cursor_slice={})
|
203
193
|
for message in self.download_retriever.read_records({}, stream_slice):
|
204
194
|
if isinstance(message, Record):
|
205
195
|
yield message.data
|
@@ -236,22 +226,3 @@ class AsyncHttpJobRepository(AsyncJobRepository):
|
|
236
226
|
cursor_slice={},
|
237
227
|
)
|
238
228
|
return stream_slice
|
239
|
-
|
240
|
-
def _get_download_url(self, job: AsyncJob) -> Iterable[str]:
|
241
|
-
if not self.url_requester:
|
242
|
-
url_response = self._polling_job_response_by_id[job.api_job_id()]
|
243
|
-
else:
|
244
|
-
stream_slice: StreamSlice = StreamSlice(
|
245
|
-
partition={
|
246
|
-
"polling_job_response": self._polling_job_response_by_id[job.api_job_id()]
|
247
|
-
},
|
248
|
-
cursor_slice={},
|
249
|
-
)
|
250
|
-
url_response = self.url_requester.send_request(stream_slice=stream_slice) # type: ignore # we expect url_requester to always be presented, otherwise raise an exception as we cannot proceed with the report
|
251
|
-
if not url_response:
|
252
|
-
raise AirbyteTracedException(
|
253
|
-
internal_message="Always expect a response or an exception from url_requester",
|
254
|
-
failure_type=FailureType.system_error,
|
255
|
-
)
|
256
|
-
|
257
|
-
yield from self.urls_extractor.extract_records(url_response) # type: ignore # we expect urls_extractor to always return list of strings
|