Skip to content

Commit 036c2e5

Browse files
committed
chore: type-check, lint, format
1 parent fa04b9d commit 036c2e5

File tree

3 files changed

+81
-84
lines changed

3 files changed

+81
-84
lines changed

airbyte_cdk/sources/declarative/models/declarative_component_schema.py

Lines changed: 43 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -618,9 +618,7 @@ class OAuthAuthenticator(BaseModel):
618618
scopes: Optional[List[str]] = Field(
619619
None,
620620
description="List of scopes that should be granted to the access token.",
621-
examples=[
622-
["crm.list.read", "crm.objects.contacts.read", "crm.schema.contacts.read"]
623-
],
621+
examples=[["crm.list.read", "crm.objects.contacts.read", "crm.schema.contacts.read"]],
624622
title="Scopes",
625623
)
626624
token_expiry_date: Optional[str] = Field(
@@ -1126,28 +1124,24 @@ class OAuthConfigSpecification(BaseModel):
11261124
class Config:
11271125
extra = Extra.allow
11281126

1129-
oauth_user_input_from_connector_config_specification: Optional[Dict[str, Any]] = (
1130-
Field(
1131-
None,
1132-
description="OAuth specific blob. This is a Json Schema used to validate Json configurations used as input to OAuth.\nMust be a valid non-nested JSON that refers to properties from ConnectorSpecification.connectionSpecification\nusing special annotation 'path_in_connector_config'.\nThese are input values the user is entering through the UI to authenticate to the connector, that might also shared\nas inputs for syncing data via the connector.\nExamples:\nif no connector values is shared during oauth flow, oauth_user_input_from_connector_config_specification=[]\nif connector values such as 'app_id' inside the top level are used to generate the API url for the oauth flow,\n oauth_user_input_from_connector_config_specification={\n app_id: {\n type: string\n path_in_connector_config: ['app_id']\n }\n }\nif connector values such as 'info.app_id' nested inside another object are used to generate the API url for the oauth flow,\n oauth_user_input_from_connector_config_specification={\n app_id: {\n type: string\n path_in_connector_config: ['info', 'app_id']\n }\n }",
1133-
examples=[
1134-
{"app_id": {"type": "string", "path_in_connector_config": ["app_id"]}},
1135-
{
1136-
"app_id": {
1137-
"type": "string",
1138-
"path_in_connector_config": ["info", "app_id"],
1139-
}
1140-
},
1141-
],
1142-
title="OAuth user input",
1143-
)
1127+
oauth_user_input_from_connector_config_specification: Optional[Dict[str, Any]] = Field(
1128+
None,
1129+
description="OAuth specific blob. This is a Json Schema used to validate Json configurations used as input to OAuth.\nMust be a valid non-nested JSON that refers to properties from ConnectorSpecification.connectionSpecification\nusing special annotation 'path_in_connector_config'.\nThese are input values the user is entering through the UI to authenticate to the connector, that might also shared\nas inputs for syncing data via the connector.\nExamples:\nif no connector values is shared during oauth flow, oauth_user_input_from_connector_config_specification=[]\nif connector values such as 'app_id' inside the top level are used to generate the API url for the oauth flow,\n oauth_user_input_from_connector_config_specification={\n app_id: {\n type: string\n path_in_connector_config: ['app_id']\n }\n }\nif connector values such as 'info.app_id' nested inside another object are used to generate the API url for the oauth flow,\n oauth_user_input_from_connector_config_specification={\n app_id: {\n type: string\n path_in_connector_config: ['info', 'app_id']\n }\n }",
1130+
examples=[
1131+
{"app_id": {"type": "string", "path_in_connector_config": ["app_id"]}},
1132+
{
1133+
"app_id": {
1134+
"type": "string",
1135+
"path_in_connector_config": ["info", "app_id"],
1136+
}
1137+
},
1138+
],
1139+
title="OAuth user input",
11441140
)
1145-
oauth_connector_input_specification: Optional[OauthConnectorInputSpecification] = (
1146-
Field(
1147-
None,
1148-
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`, {{ {{my_var_a}}:{{my_var_b}} | base64Encoder }}\n + base64Decorer - decode from `base64` encoded string, {{ {{my_string_variable_or_string_value}} | base64Decoder }}\n + urlEncoder - encode the input string to URL-like format, {{ https://test.host.com/endpoint | urlEncoder}}\n + urlDecorer - decode the input url-encoded string into text format, {{ urlDecoder:https%3A%2F%2Fairbyte.io | urlDecoder}}\n + codeChallengeS256 - get the `codeChallenge` encoded value to provide additional data-provider specific authorisation values, {{ {{state_value}} | codeChallengeS256 }}\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_value}}&{{redirect_uri_key}}={{ {{redirect_uri_value}} | urlEncoder}}&{{state_key}}={{state_value}}",\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_value }}",\n "{{ client_id_key }}": "{{ client_id_value }}",\n "{{ client_secret_key }}": "{{ client_secret_value }}"\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 }',
1149-
title="DeclarativeOAuth Connector Specification",
1150-
)
1141+
oauth_connector_input_specification: Optional[OauthConnectorInputSpecification] = Field(
1142+
None,
1143+
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`, {{ {{my_var_a}}:{{my_var_b}} | base64Encoder }}\n + base64Decorer - decode from `base64` encoded string, {{ {{my_string_variable_or_string_value}} | base64Decoder }}\n + urlEncoder - encode the input string to URL-like format, {{ https://test.host.com/endpoint | urlEncoder}}\n + urlDecorer - decode the input url-encoded string into text format, {{ urlDecoder:https%3A%2F%2Fairbyte.io | urlDecoder}}\n + codeChallengeS256 - get the `codeChallenge` encoded value to provide additional data-provider specific authorisation values, {{ {{state_value}} | codeChallengeS256 }}\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_value}}&{{redirect_uri_key}}={{ {{redirect_uri_value}} | urlEncoder}}&{{state_key}}={{state_value}}",\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_value }}",\n "{{ client_id_key }}": "{{ client_id_value }}",\n "{{ client_secret_key }}": "{{ client_secret_value }}"\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 }',
1144+
title="DeclarativeOAuth Connector Specification",
11511145
)
11521146
complete_oauth_output_specification: Optional[Dict[str, Any]] = Field(
11531147
None,
@@ -1165,9 +1159,7 @@ class Config:
11651159
complete_oauth_server_input_specification: Optional[Dict[str, Any]] = Field(
11661160
None,
11671161
description="OAuth specific blob. This is a Json Schema used to validate Json configurations persisted as Airbyte Server configurations.\nMust be a valid non-nested JSON describing additional fields configured by the Airbyte Instance or Workspace Admins to be used by the\nserver when completing an OAuth flow (typically exchanging an auth code for refresh token).\nExamples:\n complete_oauth_server_input_specification={\n client_id: {\n type: string\n },\n client_secret: {\n type: string\n }\n }",
1168-
examples=[
1169-
{"client_id": {"type": "string"}, "client_secret": {"type": "string"}}
1170-
],
1162+
examples=[{"client_id": {"type": "string"}, "client_secret": {"type": "string"}}],
11711163
title="OAuth input specification",
11721164
)
11731165
complete_oauth_server_output_specification: Optional[Dict[str, Any]] = Field(
@@ -1949,9 +1941,7 @@ class RecordSelector(BaseModel):
19491941
description="Responsible for filtering records to be emitted by the Source.",
19501942
title="Record Filter",
19511943
)
1952-
schema_normalization: Optional[
1953-
Union[SchemaNormalization, CustomSchemaNormalization]
1954-
] = Field(
1944+
schema_normalization: Optional[Union[SchemaNormalization, CustomSchemaNormalization]] = Field(
19551945
None,
19561946
description="Responsible for normalization according to the schema.",
19571947
title="Schema Normalization",
@@ -1975,7 +1965,7 @@ class RequestBodyGraphQL(BaseModel):
19751965

19761966

19771967
class DpathValidator(BaseModel):
1978-
type: Literal["DpathValidation"]
1968+
type: Literal["DpathValidator"]
19791969
field_path: List[str] = Field(
19801970
...,
19811971
description='List of potentially nested fields describing the full path of the field to validate. Use "*" to validate all values from an array.',
@@ -2071,17 +2061,17 @@ class Config:
20712061

20722062
class ConfigNormalizationRules(BaseModel):
20732063
config_migrations: Optional[List[RemapField]] = Field(
2074-
None,
2064+
[],
20752065
description="The config will be migrated according to these transformations and updated within the platform for subsequent syncs.",
20762066
title="Config Migrations",
20772067
)
20782068
transformations: Optional[List[RemapField]] = Field(
2079-
None,
2069+
[],
20802070
description="The list of transformations that will be applied on the incoming config at the start of a sync.",
20812071
title="Transformations",
20822072
)
20832073
validations: Optional[List[Union[DpathValidator, PredicateValidator]]] = Field(
2084-
None,
2074+
[],
20852075
description="The list of validations that will be performed on the incoming config before starting a sync",
20862076
title="Validations",
20872077
)
@@ -2258,9 +2248,7 @@ class Config:
22582248
extra = Extra.allow
22592249

22602250
type: Literal["DeclarativeStream"]
2261-
name: Optional[str] = Field(
2262-
"", description="The stream name.", example=["Users"], title="Name"
2263-
)
2251+
name: Optional[str] = Field("", description="The stream name.", example=["Users"], title="Name")
22642252
retriever: Union[SimpleRetriever, AsyncRetriever, CustomRetriever] = Field(
22652253
...,
22662254
description="Component used to coordinate how records are extracted across stream slices and request pages.",
@@ -2438,20 +2426,18 @@ class HttpRequester(BaseModelWithDeprecations):
24382426
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.",
24392427
title="Fetch Properties from Endpoint",
24402428
)
2441-
request_parameters: Optional[Union[Dict[str, Union[str, QueryProperties]], str]] = (
2442-
Field(
2443-
None,
2444-
description="Specifies the query parameters that should be set on an outgoing HTTP request given the inputs.",
2445-
examples=[
2446-
{"unit": "day"},
2447-
{
2448-
"query": 'last_event_time BETWEEN TIMESTAMP "{{ stream_interval.start_time }}" AND TIMESTAMP "{{ stream_interval.end_time }}"'
2449-
},
2450-
{"searchIn": "{{ ','.join(config.get('search_in', [])) }}"},
2451-
{"sort_by[asc]": "updated_at"},
2452-
],
2453-
title="Query Parameters",
2454-
)
2429+
request_parameters: Optional[Union[Dict[str, Union[str, QueryProperties]], str]] = Field(
2430+
None,
2431+
description="Specifies the query parameters that should be set on an outgoing HTTP request given the inputs.",
2432+
examples=[
2433+
{"unit": "day"},
2434+
{
2435+
"query": 'last_event_time BETWEEN TIMESTAMP "{{ stream_interval.start_time }}" AND TIMESTAMP "{{ stream_interval.end_time }}"'
2436+
},
2437+
{"searchIn": "{{ ','.join(config.get('search_in', [])) }}"},
2438+
{"sort_by[asc]": "updated_at"},
2439+
],
2440+
title="Query Parameters",
24552441
)
24562442
request_headers: Optional[Union[Dict[str, str], str]] = Field(
24572443
None,
@@ -2641,9 +2627,7 @@ class QueryProperties(BaseModel):
26412627

26422628
class StateDelegatingStream(BaseModel):
26432629
type: Literal["StateDelegatingStream"]
2644-
name: str = Field(
2645-
..., description="The stream name.", example=["Users"], title="Name"
2646-
)
2630+
name: str = Field(..., description="The stream name.", example=["Users"], title="Name")
26472631
full_refresh_stream: DeclarativeStream = Field(
26482632
...,
26492633
description="Component used to coordinate how records are extracted across stream slices and request pages when the state is empty or not provided.",
@@ -2732,9 +2716,7 @@ class AsyncRetriever(BaseModel):
27322716
)
27332717
download_extractor: Optional[
27342718
Union[DpathExtractor, CustomRecordExtractor, ResponseToFileExtractor]
2735-
] = Field(
2736-
None, description="Responsible for fetching the records from provided urls."
2737-
)
2719+
] = Field(None, description="Responsible for fetching the records from provided urls.")
27382720
creation_requester: Union[HttpRequester, CustomRequester] = Field(
27392721
...,
27402722
description="Requester component that describes how to prepare HTTP requests to send to the source API to create the async server-side job.",
@@ -2874,12 +2856,10 @@ class DynamicDeclarativeStream(BaseModel):
28742856
stream_template: DeclarativeStream = Field(
28752857
..., description="Reference to the stream template.", title="Stream Template"
28762858
)
2877-
components_resolver: Union[HttpComponentsResolver, ConfigComponentsResolver] = (
2878-
Field(
2879-
...,
2880-
description="Component resolve and populates stream templates with components values.",
2881-
title="Components Resolver",
2882-
)
2859+
components_resolver: Union[HttpComponentsResolver, ConfigComponentsResolver] = Field(
2860+
...,
2861+
description="Component resolve and populates stream templates with components values.",
2862+
title="Components Resolver",
28832863
)
28842864

28852865

airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
)
3333
from airbyte_cdk.models import FailureType, Level
3434
from airbyte_cdk.sources.connector_state_manager import ConnectorStateManager
35+
from airbyte_cdk.sources.declarative import transformations
3536
from airbyte_cdk.sources.declarative.async_job.job_orchestrator import AsyncJobOrchestrator
3637
from airbyte_cdk.sources.declarative.async_job.job_tracker import JobTracker
3738
from airbyte_cdk.sources.declarative.async_job.repository import AsyncJobRepository
@@ -3467,26 +3468,32 @@ def _get_job_timeout() -> datetime.timedelta:
34673468

34683469
def create_spec(self, model: SpecModel, config: Config, **kwargs: Any) -> Spec:
34693470
config_migrations = []
3470-
transformations = []
3471-
validations = []
3472-
3473-
for migration in model.config_normalization_rules.config_migrations:
3474-
config_migrations.append(self._create_component_from_model(migration, config))
3475-
3476-
for transformation in model.config_normalization_rules.transformations:
3477-
transformations.append(self._create_component_from_model(transformation, config))
3471+
config_transformations = []
3472+
config_validations = []
3473+
3474+
if model.config_normalization_rules:
3475+
if model.config_normalization_rules.config_migrations:
3476+
for migration in model.config_normalization_rules.config_migrations:
3477+
config_migrations.append(self._create_component_from_model(migration, config))
3478+
3479+
if model.config_normalization_rules.transformations:
3480+
for transformation in model.config_normalization_rules.transformations:
3481+
config_transformations.append(
3482+
self._create_component_from_model(transformation, config)
3483+
)
34783484

3479-
for validation in model.config_normalization_rules.validations:
3480-
validations.append(self._create_component_from_model(validation, config))
3485+
if model.config_normalization_rules.validations:
3486+
for validation in model.config_normalization_rules.validations:
3487+
config_validations.append(self._create_component_from_model(validation, config))
34813488

34823489
return Spec(
34833490
connection_specification=model.connection_specification,
34843491
documentation_url=model.documentation_url,
34853492
advanced_auth=model.advanced_auth,
34863493
parameters={},
34873494
config_migrations=config_migrations,
3488-
transformations=transformations,
3489-
validations=validations,
3495+
config_transformations=config_transformations,
3496+
config_validations=config_validations,
34903497
)
34913498

34923499
def create_substream_partition_router(

0 commit comments

Comments
 (0)