airbyte-cdk 6.45.10__py3-none-any.whl → 6.46.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/cli/__init__.py +9 -1
- airbyte_cdk/cli/airbyte_cdk/__init__.py +86 -0
- airbyte_cdk/cli/airbyte_cdk/_connector.py +179 -0
- airbyte_cdk/cli/airbyte_cdk/_image.py +95 -0
- airbyte_cdk/cli/airbyte_cdk/_manifest.py +24 -0
- airbyte_cdk/cli/airbyte_cdk/_secrets.py +150 -0
- airbyte_cdk/cli/airbyte_cdk/_util.py +43 -0
- airbyte_cdk/cli/airbyte_cdk/_version.py +13 -0
- airbyte_cdk/connector_builder/connector_builder_handler.py +10 -0
- airbyte_cdk/models/connector_metadata.py +97 -0
- airbyte_cdk/sources/declarative/declarative_component_schema.yaml +108 -79
- airbyte_cdk/sources/declarative/manifest_declarative_source.py +122 -45
- airbyte_cdk/sources/declarative/models/declarative_component_schema.py +87 -82
- airbyte_cdk/sources/declarative/parsers/custom_exceptions.py +9 -0
- airbyte_cdk/sources/declarative/parsers/manifest_component_transformer.py +2 -2
- airbyte_cdk/sources/declarative/parsers/manifest_normalizer.py +462 -0
- airbyte_cdk/sources/declarative/parsers/manifest_reference_resolver.py +2 -2
- airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py +24 -24
- airbyte_cdk/test/standard_tests/connector_base.py +51 -25
- airbyte_cdk/test/standard_tests/declarative_sources.py +3 -1
- airbyte_cdk/test/standard_tests/test_resources.py +69 -0
- airbyte_cdk/test/standard_tests/util.py +79 -0
- airbyte_cdk/utils/docker.py +337 -0
- airbyte_cdk/utils/docker_image_templates.py +101 -0
- {airbyte_cdk-6.45.10.dist-info → airbyte_cdk-6.46.0.dist-info}/METADATA +6 -1
- {airbyte_cdk-6.45.10.dist-info → airbyte_cdk-6.46.0.dist-info}/RECORD +30 -17
- {airbyte_cdk-6.45.10.dist-info → airbyte_cdk-6.46.0.dist-info}/entry_points.txt +1 -0
- {airbyte_cdk-6.45.10.dist-info → airbyte_cdk-6.46.0.dist-info}/LICENSE.txt +0 -0
- {airbyte_cdk-6.45.10.dist-info → airbyte_cdk-6.46.0.dist-info}/LICENSE_SHORT +0 -0
- {airbyte_cdk-6.45.10.dist-info → airbyte_cdk-6.46.0.dist-info}/WHEEL +0 -0
@@ -29,7 +29,9 @@ from airbyte_cdk.sources.declarative.declarative_source import DeclarativeSource
|
|
29
29
|
from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
|
30
30
|
DeclarativeStream as DeclarativeStreamModel,
|
31
31
|
)
|
32
|
-
from airbyte_cdk.sources.declarative.models.declarative_component_schema import
|
32
|
+
from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
|
33
|
+
Spec as SpecModel,
|
34
|
+
)
|
33
35
|
from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
|
34
36
|
StateDelegatingStream as StateDelegatingStreamModel,
|
35
37
|
)
|
@@ -39,6 +41,9 @@ from airbyte_cdk.sources.declarative.parsers.custom_code_compiler import (
|
|
39
41
|
from airbyte_cdk.sources.declarative.parsers.manifest_component_transformer import (
|
40
42
|
ManifestComponentTransformer,
|
41
43
|
)
|
44
|
+
from airbyte_cdk.sources.declarative.parsers.manifest_normalizer import (
|
45
|
+
ManifestNormalizer,
|
46
|
+
)
|
42
47
|
from airbyte_cdk.sources.declarative.parsers.manifest_reference_resolver import (
|
43
48
|
ManifestReferenceResolver,
|
44
49
|
)
|
@@ -57,6 +62,24 @@ from airbyte_cdk.sources.utils.slice_logger import (
|
|
57
62
|
from airbyte_cdk.utils.traced_exception import AirbyteTracedException
|
58
63
|
|
59
64
|
|
65
|
+
def _get_declarative_component_schema() -> Dict[str, Any]:
|
66
|
+
try:
|
67
|
+
raw_component_schema = pkgutil.get_data(
|
68
|
+
"airbyte_cdk", "sources/declarative/declarative_component_schema.yaml"
|
69
|
+
)
|
70
|
+
if raw_component_schema is not None:
|
71
|
+
declarative_component_schema = yaml.load(raw_component_schema, Loader=yaml.SafeLoader)
|
72
|
+
return declarative_component_schema # type: ignore
|
73
|
+
else:
|
74
|
+
raise RuntimeError(
|
75
|
+
"Failed to read manifest component json schema required for deduplication"
|
76
|
+
)
|
77
|
+
except FileNotFoundError as e:
|
78
|
+
raise FileNotFoundError(
|
79
|
+
f"Failed to read manifest component json schema required for deduplication: {e}"
|
80
|
+
)
|
81
|
+
|
82
|
+
|
60
83
|
class ManifestDeclarativeSource(DeclarativeSource):
|
61
84
|
"""Declarative source defined by a manifest of low-code components that define source connector behavior"""
|
62
85
|
|
@@ -68,7 +91,8 @@ class ManifestDeclarativeSource(DeclarativeSource):
|
|
68
91
|
debug: bool = False,
|
69
92
|
emit_connector_builder_messages: bool = False,
|
70
93
|
component_factory: Optional[ModelToComponentFactory] = None,
|
71
|
-
|
94
|
+
normalize_manifest: Optional[bool] = False,
|
95
|
+
) -> None:
|
72
96
|
"""
|
73
97
|
Args:
|
74
98
|
config: The provided config dict.
|
@@ -76,21 +100,16 @@ class ManifestDeclarativeSource(DeclarativeSource):
|
|
76
100
|
debug: True if debug mode is enabled.
|
77
101
|
emit_connector_builder_messages: True if messages should be emitted to the connector builder.
|
78
102
|
component_factory: optional factory if ModelToComponentFactory's default behavior needs to be tweaked.
|
103
|
+
normalize_manifest: Optional flag to indicate if the manifest should be normalized.
|
79
104
|
"""
|
80
105
|
self.logger = logging.getLogger(f"airbyte.{self.name}")
|
81
|
-
|
82
|
-
|
83
|
-
if "type" not in manifest:
|
84
|
-
manifest["type"] = "DeclarativeSource"
|
85
|
-
|
106
|
+
self._should_normalize = normalize_manifest
|
107
|
+
self._declarative_component_schema = _get_declarative_component_schema()
|
86
108
|
# If custom components are needed, locate and/or register them.
|
87
109
|
self.components_module: ModuleType | None = get_registered_components_module(config=config)
|
110
|
+
# resolve all components in the manifest
|
111
|
+
self._source_config = self._preprocess_manifest(dict(source_config))
|
88
112
|
|
89
|
-
resolved_source_config = ManifestReferenceResolver().preprocess_manifest(manifest)
|
90
|
-
propagated_source_config = ManifestComponentTransformer().propagate_types_and_parameters(
|
91
|
-
"", resolved_source_config, {}
|
92
|
-
)
|
93
|
-
self._source_config = propagated_source_config
|
94
113
|
self._debug = debug
|
95
114
|
self._emit_connector_builder_messages = emit_connector_builder_messages
|
96
115
|
self._constructor = (
|
@@ -105,14 +124,81 @@ class ManifestDeclarativeSource(DeclarativeSource):
|
|
105
124
|
self._slice_logger: SliceLogger = (
|
106
125
|
AlwaysLogSliceLogger() if emit_connector_builder_messages else DebugSliceLogger()
|
107
126
|
)
|
108
|
-
|
109
127
|
self._config = config or {}
|
128
|
+
|
129
|
+
# validate resolved manifest against the declarative component schema
|
110
130
|
self._validate_source()
|
111
131
|
|
132
|
+
# apply additional post-processing to the manifest
|
133
|
+
self._postprocess_manifest()
|
134
|
+
|
112
135
|
@property
|
113
136
|
def resolved_manifest(self) -> Mapping[str, Any]:
|
137
|
+
"""
|
138
|
+
Returns the resolved manifest configuration for the source.
|
139
|
+
|
140
|
+
This property provides access to the internal source configuration as a mapping,
|
141
|
+
which contains all settings and parameters required to define the source's behavior.
|
142
|
+
|
143
|
+
Returns:
|
144
|
+
Mapping[str, Any]: The resolved source configuration manifest.
|
145
|
+
"""
|
114
146
|
return self._source_config
|
115
147
|
|
148
|
+
def _preprocess_manifest(self, manifest: Dict[str, Any]) -> Dict[str, Any]:
|
149
|
+
"""
|
150
|
+
Preprocesses the provided manifest dictionary by resolving any manifest references.
|
151
|
+
|
152
|
+
This method modifies the input manifest in place, resolving references using the
|
153
|
+
ManifestReferenceResolver to ensure all references within the manifest are properly handled.
|
154
|
+
|
155
|
+
Args:
|
156
|
+
manifest (Dict[str, Any]): The manifest dictionary to preprocess and resolve references in.
|
157
|
+
|
158
|
+
Returns:
|
159
|
+
None
|
160
|
+
"""
|
161
|
+
# For ease of use we don't require the type to be specified at the top level manifest, but it should be included during processing
|
162
|
+
manifest = self._fix_source_type(manifest)
|
163
|
+
# Resolve references in the manifest
|
164
|
+
resolved_manifest = ManifestReferenceResolver().preprocess_manifest(manifest)
|
165
|
+
# Propagate types and parameters throughout the manifest
|
166
|
+
propagated_manifest = ManifestComponentTransformer().propagate_types_and_parameters(
|
167
|
+
"", resolved_manifest, {}
|
168
|
+
)
|
169
|
+
|
170
|
+
return propagated_manifest
|
171
|
+
|
172
|
+
def _postprocess_manifest(self) -> None:
|
173
|
+
"""
|
174
|
+
Post-processes the manifest after validation.
|
175
|
+
This method is responsible for any additional modifications or transformations needed
|
176
|
+
after the manifest has been validated and before it is used in the source.
|
177
|
+
"""
|
178
|
+
# apply manifest normalization, if required
|
179
|
+
self._normalize_manifest()
|
180
|
+
|
181
|
+
def _normalize_manifest(self) -> None:
|
182
|
+
"""
|
183
|
+
This method is used to normalize the manifest. It should be called after the manifest has been validated.
|
184
|
+
|
185
|
+
Connector Builder UI rendering requires the manifest to be in a specific format.
|
186
|
+
- references have been resolved
|
187
|
+
- the commonly used definitions are extracted to the `definitions.linked.*`
|
188
|
+
"""
|
189
|
+
if self._should_normalize:
|
190
|
+
normalizer = ManifestNormalizer(self._source_config, self._declarative_component_schema)
|
191
|
+
self._source_config = normalizer.normalize()
|
192
|
+
|
193
|
+
def _fix_source_type(self, manifest: Dict[str, Any]) -> Dict[str, Any]:
|
194
|
+
"""
|
195
|
+
Fix the source type in the manifest. This is necessary because the source type is not always set in the manifest.
|
196
|
+
"""
|
197
|
+
if "type" not in manifest:
|
198
|
+
manifest["type"] = "DeclarativeSource"
|
199
|
+
|
200
|
+
return manifest
|
201
|
+
|
116
202
|
@property
|
117
203
|
def message_repository(self) -> MessageRepository:
|
118
204
|
return self._message_repository
|
@@ -120,7 +206,9 @@ class ManifestDeclarativeSource(DeclarativeSource):
|
|
120
206
|
@property
|
121
207
|
def dynamic_streams(self) -> List[Dict[str, Any]]:
|
122
208
|
return self._dynamic_stream_configs(
|
123
|
-
manifest=self._source_config,
|
209
|
+
manifest=self._source_config,
|
210
|
+
config=self._config,
|
211
|
+
with_dynamic_stream_name=True,
|
124
212
|
)
|
125
213
|
|
126
214
|
@property
|
@@ -143,7 +231,10 @@ class ManifestDeclarativeSource(DeclarativeSource):
|
|
143
231
|
|
144
232
|
def streams(self, config: Mapping[str, Any]) -> List[Stream]:
|
145
233
|
self._emit_manifest_debug_message(
|
146
|
-
extra_args={
|
234
|
+
extra_args={
|
235
|
+
"source_name": self.name,
|
236
|
+
"parsed_config": json.dumps(self._source_config),
|
237
|
+
}
|
147
238
|
)
|
148
239
|
|
149
240
|
stream_configs = self._stream_configs(self._source_config) + self._dynamic_stream_configs(
|
@@ -156,9 +247,11 @@ class ManifestDeclarativeSource(DeclarativeSource):
|
|
156
247
|
|
157
248
|
source_streams = [
|
158
249
|
self._constructor.create_component(
|
159
|
-
|
160
|
-
|
161
|
-
|
250
|
+
(
|
251
|
+
StateDelegatingStreamModel
|
252
|
+
if stream_config.get("type") == StateDelegatingStreamModel.__name__
|
253
|
+
else DeclarativeStreamModel
|
254
|
+
),
|
162
255
|
stream_config,
|
163
256
|
config,
|
164
257
|
emit_connector_builder_messages=self._emit_connector_builder_messages,
|
@@ -174,7 +267,9 @@ class ManifestDeclarativeSource(DeclarativeSource):
|
|
174
267
|
) -> List[Dict[str, Any]]:
|
175
268
|
parent_streams = set()
|
176
269
|
|
177
|
-
def update_with_cache_parent_configs(
|
270
|
+
def update_with_cache_parent_configs(
|
271
|
+
parent_configs: list[dict[str, Any]],
|
272
|
+
) -> None:
|
178
273
|
for parent_config in parent_configs:
|
179
274
|
parent_streams.add(parent_config["stream"]["name"])
|
180
275
|
if parent_config["stream"]["type"] == "StateDelegatingStream":
|
@@ -229,7 +324,10 @@ class ManifestDeclarativeSource(DeclarativeSource):
|
|
229
324
|
"""
|
230
325
|
self._configure_logger_level(logger)
|
231
326
|
self._emit_manifest_debug_message(
|
232
|
-
extra_args={
|
327
|
+
extra_args={
|
328
|
+
"source_name": self.name,
|
329
|
+
"parsed_config": json.dumps(self._source_config),
|
330
|
+
}
|
233
331
|
)
|
234
332
|
|
235
333
|
spec = self._source_config.get("spec")
|
@@ -266,32 +364,9 @@ class ManifestDeclarativeSource(DeclarativeSource):
|
|
266
364
|
"""
|
267
365
|
Validates the connector manifest against the declarative component schema
|
268
366
|
"""
|
269
|
-
try:
|
270
|
-
raw_component_schema = pkgutil.get_data(
|
271
|
-
"airbyte_cdk", "sources/declarative/declarative_component_schema.yaml"
|
272
|
-
)
|
273
|
-
if raw_component_schema is not None:
|
274
|
-
declarative_component_schema = yaml.load(
|
275
|
-
raw_component_schema, Loader=yaml.SafeLoader
|
276
|
-
)
|
277
|
-
else:
|
278
|
-
raise RuntimeError(
|
279
|
-
"Failed to read manifest component json schema required for validation"
|
280
|
-
)
|
281
|
-
except FileNotFoundError as e:
|
282
|
-
raise FileNotFoundError(
|
283
|
-
f"Failed to read manifest component json schema required for validation: {e}"
|
284
|
-
)
|
285
|
-
|
286
|
-
streams = self._source_config.get("streams")
|
287
|
-
dynamic_streams = self._source_config.get("dynamic_streams")
|
288
|
-
if not (streams or dynamic_streams):
|
289
|
-
raise ValidationError(
|
290
|
-
f"A valid manifest should have at least one stream defined. Got {streams}"
|
291
|
-
)
|
292
367
|
|
293
368
|
try:
|
294
|
-
validate(self._source_config,
|
369
|
+
validate(self._source_config, self._declarative_component_schema)
|
295
370
|
except ValidationError as e:
|
296
371
|
raise ValidationError(
|
297
372
|
"Validation against json schema defined in declarative_component_schema.yaml schema failed"
|
@@ -389,7 +464,9 @@ class ManifestDeclarativeSource(DeclarativeSource):
|
|
389
464
|
|
390
465
|
# Create a resolver for dynamic components based on type
|
391
466
|
components_resolver = self._constructor.create_component(
|
392
|
-
COMPONENTS_RESOLVER_TYPE_MAPPING[resolver_type],
|
467
|
+
COMPONENTS_RESOLVER_TYPE_MAPPING[resolver_type],
|
468
|
+
components_resolver_config,
|
469
|
+
config,
|
393
470
|
)
|
394
471
|
|
395
472
|
stream_template_config = dynamic_definition["stream_template"]
|