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.
Files changed (30) hide show
  1. airbyte_cdk/cli/__init__.py +9 -1
  2. airbyte_cdk/cli/airbyte_cdk/__init__.py +86 -0
  3. airbyte_cdk/cli/airbyte_cdk/_connector.py +179 -0
  4. airbyte_cdk/cli/airbyte_cdk/_image.py +95 -0
  5. airbyte_cdk/cli/airbyte_cdk/_manifest.py +24 -0
  6. airbyte_cdk/cli/airbyte_cdk/_secrets.py +150 -0
  7. airbyte_cdk/cli/airbyte_cdk/_util.py +43 -0
  8. airbyte_cdk/cli/airbyte_cdk/_version.py +13 -0
  9. airbyte_cdk/connector_builder/connector_builder_handler.py +10 -0
  10. airbyte_cdk/models/connector_metadata.py +97 -0
  11. airbyte_cdk/sources/declarative/declarative_component_schema.yaml +108 -79
  12. airbyte_cdk/sources/declarative/manifest_declarative_source.py +122 -45
  13. airbyte_cdk/sources/declarative/models/declarative_component_schema.py +87 -82
  14. airbyte_cdk/sources/declarative/parsers/custom_exceptions.py +9 -0
  15. airbyte_cdk/sources/declarative/parsers/manifest_component_transformer.py +2 -2
  16. airbyte_cdk/sources/declarative/parsers/manifest_normalizer.py +462 -0
  17. airbyte_cdk/sources/declarative/parsers/manifest_reference_resolver.py +2 -2
  18. airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py +24 -24
  19. airbyte_cdk/test/standard_tests/connector_base.py +51 -25
  20. airbyte_cdk/test/standard_tests/declarative_sources.py +3 -1
  21. airbyte_cdk/test/standard_tests/test_resources.py +69 -0
  22. airbyte_cdk/test/standard_tests/util.py +79 -0
  23. airbyte_cdk/utils/docker.py +337 -0
  24. airbyte_cdk/utils/docker_image_templates.py +101 -0
  25. {airbyte_cdk-6.45.10.dist-info → airbyte_cdk-6.46.0.dist-info}/METADATA +6 -1
  26. {airbyte_cdk-6.45.10.dist-info → airbyte_cdk-6.46.0.dist-info}/RECORD +30 -17
  27. {airbyte_cdk-6.45.10.dist-info → airbyte_cdk-6.46.0.dist-info}/entry_points.txt +1 -0
  28. {airbyte_cdk-6.45.10.dist-info → airbyte_cdk-6.46.0.dist-info}/LICENSE.txt +0 -0
  29. {airbyte_cdk-6.45.10.dist-info → airbyte_cdk-6.46.0.dist-info}/LICENSE_SHORT +0 -0
  30. {airbyte_cdk-6.45.10.dist-info → airbyte_cdk-6.46.0.dist-info}/WHEEL +0 -0
@@ -10,9 +10,9 @@ from airbyte_cdk.sources.declarative.concurrent_declarative_source import (
10
10
  ConcurrentDeclarativeSource,
11
11
  )
12
12
  from airbyte_cdk.test.standard_tests._job_runner import IConnector
13
- from airbyte_cdk.test.standard_tests.connector_base import MANIFEST_YAML
14
13
  from airbyte_cdk.test.standard_tests.models import ConnectorTestScenario
15
14
  from airbyte_cdk.test.standard_tests.source_base import SourceTestSuiteBase
15
+ from airbyte_cdk.test.standard_tests.test_resources import MANIFEST_YAML
16
16
 
17
17
 
18
18
  def md5_checksum(file_path: Path) -> str:
@@ -35,6 +35,8 @@ class DeclarativeSourceTestSuite(SourceTestSuiteBase):
35
35
  `components.py` file (if it exists) in the connector's directory.
36
36
  """
37
37
 
38
+ connector: type[IConnector] | None = None
39
+
38
40
  @classproperty
39
41
  def manifest_yaml_path(cls) -> Path:
40
42
  """Get the path to the manifest.yaml file."""
@@ -0,0 +1,69 @@
1
+ # Copyright (c) 2025 Airbyte, Inc., all rights reserved.
2
+ """Resources for Airbyte CDK tests."""
3
+
4
+ from contextlib import suppress
5
+ from pathlib import Path
6
+
7
+ ACCEPTANCE_TEST_CONFIG = "acceptance-test-config.yml"
8
+ MANIFEST_YAML = "manifest.yaml"
9
+ METADATA_YAML = "metadata.yaml"
10
+
11
+
12
+ def find_connector_root(from_paths: list[Path]) -> Path:
13
+ """Find the root directory of the connector."""
14
+ for path in from_paths:
15
+ # If we reach here, we didn't find the manifest file in any parent directory
16
+ # Check if the manifest file exists in the current directory
17
+ for parent in [path, *path.parents]:
18
+ if (parent / METADATA_YAML).exists():
19
+ return parent
20
+ if (parent / MANIFEST_YAML).exists():
21
+ return parent
22
+ if (parent / ACCEPTANCE_TEST_CONFIG).exists():
23
+ return parent
24
+ if parent.name == "airbyte_cdk":
25
+ break
26
+
27
+ raise FileNotFoundError(
28
+ "Could not find connector root directory relative to the provided directories: "
29
+ f"'{str(from_paths)}'."
30
+ )
31
+
32
+
33
+ def find_connector_root_from_name(connector_name: str) -> Path:
34
+ """Find the root directory of the connector from its name."""
35
+ with suppress(FileNotFoundError):
36
+ return find_connector_root([Path(connector_name)])
37
+
38
+ # If the connector name is not found, check if we are in the airbyte monorepo
39
+ # and try to find the connector root from the current directory.
40
+
41
+ cwd: Path = Path().absolute()
42
+
43
+ if "airbyte" not in cwd.parts:
44
+ raise FileNotFoundError(
45
+ "Could not find connector root directory relative and we are not in the airbyte repo. "
46
+ f"Current directory: {cwd} "
47
+ )
48
+
49
+ # Find the connector root from the current directory
50
+
51
+ airbyte_repo_root: Path
52
+ for parent in [cwd, *cwd.parents]:
53
+ if parent.name == "airbyte":
54
+ airbyte_repo_root = parent
55
+ break
56
+ else:
57
+ raise FileNotFoundError(
58
+ "Could not find connector root directory relative and we are not in the airbyte repo."
59
+ )
60
+
61
+ expected_connector_dir: Path = (
62
+ airbyte_repo_root / "airbyte-integrations" / "connectors" / connector_name
63
+ )
64
+ if not expected_connector_dir.exists():
65
+ raise FileNotFoundError(
66
+ f"Could not find connector directory '{expected_connector_dir}' relative to the airbyte repo."
67
+ )
68
+
69
+ return expected_connector_dir
@@ -0,0 +1,79 @@
1
+ # Copyright (c) 2025 Airbyte, Inc., all rights reserved.
2
+ """Utility and factory functions for testing Airbyte connectors."""
3
+
4
+ from pathlib import Path
5
+ from typing import Any, Literal
6
+
7
+ import yaml
8
+
9
+ from airbyte_cdk.test.standard_tests.connector_base import ConnectorTestSuiteBase
10
+ from airbyte_cdk.test.standard_tests.declarative_sources import (
11
+ DeclarativeSourceTestSuite,
12
+ )
13
+ from airbyte_cdk.test.standard_tests.destination_base import DestinationTestSuiteBase
14
+ from airbyte_cdk.test.standard_tests.source_base import SourceTestSuiteBase
15
+ from airbyte_cdk.test.standard_tests.test_resources import (
16
+ METADATA_YAML,
17
+ find_connector_root_from_name,
18
+ )
19
+
20
+ TEST_CLASS_MAPPING: dict[
21
+ Literal["python", "manifest-only", "declarative"], type[ConnectorTestSuiteBase]
22
+ ] = {
23
+ "python": SourceTestSuiteBase,
24
+ "manifest-only": DeclarativeSourceTestSuite,
25
+ # "declarative": DeclarativeSourceTestSuite,
26
+ }
27
+
28
+
29
+ def create_connector_test_suite(
30
+ *,
31
+ connector_name: str | None = None,
32
+ connector_directory: Path | None = None,
33
+ ) -> type[ConnectorTestSuiteBase]:
34
+ """Get the test class for the specified connector name or path."""
35
+ if connector_name and connector_directory:
36
+ raise ValueError("Specify either `connector_name` or `connector_directory`, not both.")
37
+ if not connector_name and not connector_directory:
38
+ raise ValueError("Specify either `connector_name` or `connector_directory`.")
39
+
40
+ if connector_name:
41
+ connector_directory = find_connector_root_from_name(
42
+ connector_name,
43
+ )
44
+ else:
45
+ # By here, we know that connector_directory is not None
46
+ # but connector_name is None. Set the connector_name.
47
+ assert connector_directory is not None, "connector_directory should not be None here."
48
+ connector_name = connector_directory.name
49
+
50
+ metadata_yaml_path = connector_directory / METADATA_YAML
51
+ if not metadata_yaml_path.exists():
52
+ raise FileNotFoundError(
53
+ f"Could not find metadata YAML file '{metadata_yaml_path}' relative to the connector directory."
54
+ )
55
+ metadata_dict: dict[str, Any] = yaml.safe_load(metadata_yaml_path.read_text())
56
+ metadata_tags = metadata_dict["data"].get("tags", [])
57
+ for language_option in TEST_CLASS_MAPPING:
58
+ if f"language:{language_option}" in metadata_tags:
59
+ language = language_option
60
+ test_suite_class = TEST_CLASS_MAPPING[language]
61
+ break
62
+ else:
63
+ raise ValueError(
64
+ f"Unsupported connector type. "
65
+ f"Supported language values are: {', '.join(TEST_CLASS_MAPPING.keys())}. "
66
+ f"Found tags: {', '.join(metadata_tags)}"
67
+ )
68
+
69
+ subclass_overrides: dict[str, Any] = {
70
+ "get_connector_root_dir": lambda: connector_directory,
71
+ }
72
+
73
+ TestSuiteAuto = type(
74
+ "TestSuiteAuto",
75
+ (test_suite_class,),
76
+ subclass_overrides,
77
+ )
78
+
79
+ return TestSuiteAuto
@@ -0,0 +1,337 @@
1
+ """Docker build utilities for Airbyte CDK."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import logging
7
+ import os
8
+ import subprocess
9
+ import sys
10
+ from dataclasses import dataclass
11
+ from enum import Enum
12
+ from pathlib import Path
13
+
14
+ import click
15
+
16
+ from airbyte_cdk.models.connector_metadata import ConnectorLanguage, MetadataFile
17
+ from airbyte_cdk.utils.docker_image_templates import (
18
+ DOCKERIGNORE_TEMPLATE,
19
+ MANIFEST_ONLY_DOCKERFILE_TEMPLATE,
20
+ PYTHON_CONNECTOR_DOCKERFILE_TEMPLATE,
21
+ )
22
+
23
+
24
+ @dataclass(kw_only=True)
25
+ class ConnectorImageBuildError(Exception):
26
+ """Custom exception for Docker build errors."""
27
+
28
+ error_text: str
29
+ build_args: list[str]
30
+
31
+ def __str__(self) -> str:
32
+ return "\n".join(
33
+ [
34
+ f"ConnectorImageBuildError: Could not build image.",
35
+ f"Build args: {self.build_args}",
36
+ f"Error text: {self.error_text}",
37
+ ]
38
+ )
39
+
40
+
41
+ logger = logging.getLogger(__name__)
42
+
43
+
44
+ class ArchEnum(str, Enum):
45
+ """Enum for supported architectures."""
46
+
47
+ ARM64 = "arm64"
48
+ AMD64 = "amd64"
49
+
50
+
51
+ def _build_image(
52
+ context_dir: Path,
53
+ dockerfile: Path,
54
+ metadata: MetadataFile,
55
+ tag: str,
56
+ arch: ArchEnum,
57
+ build_args: dict[str, str | None] | None = None,
58
+ ) -> str:
59
+ """Build a Docker image for the specified architecture.
60
+
61
+ Returns the tag of the built image.
62
+
63
+ Raises: ConnectorImageBuildError if the build fails.
64
+ """
65
+ docker_args: list[str] = [
66
+ "docker",
67
+ "build",
68
+ "--platform",
69
+ f"linux/{arch.value}",
70
+ "--file",
71
+ str(dockerfile),
72
+ "--label",
73
+ f"io.airbyte.version={metadata.data.dockerImageTag}",
74
+ "--label",
75
+ f"io.airbyte.name={metadata.data.dockerRepository}",
76
+ ]
77
+ if build_args:
78
+ for key, value in build_args.items():
79
+ if value is not None:
80
+ docker_args.append(f"--build-arg={key}={value}")
81
+ else:
82
+ docker_args.append(f"--build-arg={key}")
83
+ docker_args.extend(
84
+ [
85
+ "-t",
86
+ tag,
87
+ str(context_dir),
88
+ ]
89
+ )
90
+
91
+ print(f"Building image: {tag} ({arch})")
92
+ try:
93
+ run_docker_command(
94
+ docker_args,
95
+ check=True,
96
+ )
97
+ except subprocess.CalledProcessError as e:
98
+ raise ConnectorImageBuildError(
99
+ error_text=e.stderr,
100
+ build_args=docker_args,
101
+ ) from e
102
+
103
+ return tag
104
+
105
+
106
+ def _tag_image(
107
+ tag: str,
108
+ new_tags: list[str] | str,
109
+ ) -> None:
110
+ """Build a Docker image for the specified architecture.
111
+
112
+ Returns the tag of the built image.
113
+
114
+ Raises:
115
+ ConnectorImageBuildError: If the docker tag command fails.
116
+ """
117
+ if not isinstance(new_tags, list):
118
+ new_tags = [new_tags]
119
+
120
+ for new_tag in new_tags:
121
+ print(f"Tagging image '{tag}' as: {new_tag}")
122
+ docker_args = [
123
+ "docker",
124
+ "tag",
125
+ tag,
126
+ new_tag,
127
+ ]
128
+ try:
129
+ run_docker_command(
130
+ docker_args,
131
+ check=True,
132
+ )
133
+ except subprocess.CalledProcessError as e:
134
+ raise ConnectorImageBuildError(
135
+ error_text=e.stderr,
136
+ build_args=docker_args,
137
+ ) from e
138
+
139
+
140
+ def build_connector_image(
141
+ connector_name: str,
142
+ connector_directory: Path,
143
+ metadata: MetadataFile,
144
+ tag: str,
145
+ primary_arch: ArchEnum = ArchEnum.ARM64, # Assume MacBook M series by default
146
+ no_verify: bool = False,
147
+ ) -> None:
148
+ """Build a connector Docker image.
149
+
150
+ This command builds a Docker image for a connector, using either
151
+ the connector's Dockerfile or a base image specified in the metadata.
152
+ The image is built for both AMD64 and ARM64 architectures.
153
+
154
+ Args:
155
+ connector_name: The name of the connector.
156
+ connector_directory: The directory containing the connector code.
157
+ metadata: The metadata of the connector.
158
+ tag: The tag to apply to the built image.
159
+ primary_arch: The primary architecture for the build (default: arm64). This
160
+ architecture will be used for the same-named tag. Both AMD64 and ARM64
161
+ images will be built, with the suffixes '-amd64' and '-arm64'.
162
+ no_verify: If True, skip verification of the built image.
163
+
164
+ Raises:
165
+ ValueError: If the connector build options are not defined in metadata.yaml.
166
+ ConnectorImageBuildError: If the image build or tag operation fails.
167
+ """
168
+ connector_kebab_name = connector_name
169
+ connector_snake_name = connector_kebab_name.replace("-", "_")
170
+
171
+ dockerfile_path = connector_directory / "build" / "docker" / "Dockerfile"
172
+ dockerignore_path = connector_directory / "build" / "docker" / "Dockerfile.dockerignore"
173
+
174
+ extra_build_script: str = ""
175
+ build_customization_path = connector_directory / "build_customization.py"
176
+ if build_customization_path.exists():
177
+ extra_build_script = str(build_customization_path)
178
+
179
+ dockerfile_path.parent.mkdir(parents=True, exist_ok=True)
180
+ if not metadata.data.connectorBuildOptions:
181
+ raise ValueError(
182
+ "Connector build options are not defined in metadata.yaml. "
183
+ "Please check the connector's metadata file."
184
+ )
185
+
186
+ base_image = metadata.data.connectorBuildOptions.baseImage
187
+
188
+ dockerfile_path.write_text(get_dockerfile_template(metadata))
189
+ dockerignore_path.write_text(DOCKERIGNORE_TEMPLATE)
190
+
191
+ build_args: dict[str, str | None] = {
192
+ "BASE_IMAGE": base_image,
193
+ "CONNECTOR_SNAKE_NAME": connector_snake_name,
194
+ "CONNECTOR_KEBAB_NAME": connector_kebab_name,
195
+ "EXTRA_BUILD_SCRIPT": extra_build_script,
196
+ }
197
+
198
+ base_tag = f"{metadata.data.dockerRepository}:{tag}"
199
+ arch_images: list[str] = []
200
+ for arch in [ArchEnum.AMD64, ArchEnum.ARM64]:
201
+ docker_tag = f"{base_tag}-{arch.value}"
202
+ docker_tag_parts = docker_tag.split("/")
203
+ if len(docker_tag_parts) > 2:
204
+ docker_tag = "/".join(docker_tag_parts[-1:])
205
+ arch_images.append(
206
+ _build_image(
207
+ context_dir=connector_directory,
208
+ dockerfile=dockerfile_path,
209
+ metadata=metadata,
210
+ tag=docker_tag,
211
+ arch=arch,
212
+ build_args=build_args,
213
+ )
214
+ )
215
+
216
+ _tag_image(
217
+ tag=f"{base_tag}-{primary_arch.value}",
218
+ new_tags=[base_tag],
219
+ )
220
+ if not no_verify:
221
+ if verify_connector_image(base_tag):
222
+ click.echo(f"Build completed successfully: {base_tag}")
223
+ sys.exit(0)
224
+ else:
225
+ click.echo(f"Built image failed verification: {base_tag}", err=True)
226
+ sys.exit(1)
227
+ else:
228
+ click.echo(f"Build completed successfully (without verification): {base_tag}")
229
+ sys.exit(0)
230
+
231
+
232
+ def get_dockerfile_template(
233
+ metadata: MetadataFile,
234
+ ) -> str:
235
+ """Get the Dockerfile template for the connector.
236
+
237
+ Args:
238
+ metadata: The metadata of the connector.
239
+ connector_name: The name of the connector.
240
+
241
+ Returns:
242
+ The Dockerfile template as a string.
243
+ """
244
+ if metadata.data.language == ConnectorLanguage.PYTHON:
245
+ return PYTHON_CONNECTOR_DOCKERFILE_TEMPLATE
246
+
247
+ if metadata.data.language == ConnectorLanguage.MANIFEST_ONLY:
248
+ return MANIFEST_ONLY_DOCKERFILE_TEMPLATE
249
+
250
+ if metadata.data.language == ConnectorLanguage.JAVA:
251
+ raise ValueError(
252
+ f"Java and Kotlin connectors are not yet supported. "
253
+ "Please use airbyte-ci or gradle to build your image."
254
+ )
255
+
256
+ raise ValueError(
257
+ f"Unsupported connector language: {metadata.data.language}. "
258
+ "Please check the connector's metadata file."
259
+ )
260
+
261
+
262
+ def run_docker_command(
263
+ cmd: list[str],
264
+ *,
265
+ check: bool = True,
266
+ capture_output: bool = False,
267
+ ) -> subprocess.CompletedProcess[str]:
268
+ """Run a Docker command as a subprocess.
269
+
270
+ Args:
271
+ cmd: The command to run as a list of strings.
272
+ check: If True, raises an exception if the command fails. If False, the caller is
273
+ responsible for checking the return code.
274
+ capture_output: If True, captures stdout and stderr and returns to the caller.
275
+ If False, the output is printed to the console.
276
+
277
+ Raises:
278
+ subprocess.CalledProcessError: If the command fails and check is True.
279
+ """
280
+ print(f"Running command: {' '.join(cmd)}")
281
+
282
+ process = subprocess.run(
283
+ cmd,
284
+ text=True,
285
+ check=check,
286
+ # If capture_output=True, stderr and stdout are captured and returned to caller:
287
+ capture_output=capture_output,
288
+ env={**os.environ, "DOCKER_BUILDKIT": "1"},
289
+ )
290
+ return process
291
+
292
+
293
+ def verify_docker_installation() -> bool:
294
+ """Verify Docker is installed and running."""
295
+ try:
296
+ run_docker_command(["docker", "--version"])
297
+ return True
298
+ except (subprocess.CalledProcessError, FileNotFoundError):
299
+ return False
300
+
301
+
302
+ def verify_connector_image(
303
+ image_name: str,
304
+ ) -> bool:
305
+ """Verify the built image by running the spec command.
306
+
307
+ Args:
308
+ image_name: The full image name with tag.
309
+
310
+ Returns:
311
+ True if the spec command succeeds, False otherwise.
312
+ """
313
+ logger.info(f"Verifying image {image_name} with 'spec' command...")
314
+
315
+ cmd = ["docker", "run", "--rm", image_name, "spec"]
316
+
317
+ try:
318
+ result = run_docker_command(
319
+ cmd,
320
+ check=True,
321
+ capture_output=True,
322
+ )
323
+ # check that the output is valid JSON
324
+ if result.stdout:
325
+ try:
326
+ json.loads(result.stdout)
327
+ except json.JSONDecodeError:
328
+ logger.error("Invalid JSON output from spec command.")
329
+ return False
330
+ else:
331
+ logger.error("No output from spec command.")
332
+ return False
333
+ except subprocess.CalledProcessError as e:
334
+ logger.error(f"Image verification failed: {e.stderr}")
335
+ return False
336
+
337
+ return True
@@ -0,0 +1,101 @@
1
+ # Copyright (c) 2025 Airbyte, Inc., all rights reserved.
2
+ """A collection of Dockerfile templates for building Airbyte connectors.
3
+
4
+ The templates are designed to be used with the Airbyte CDK and can be customized
5
+ for different connectors and architectures.
6
+
7
+ These templates are used to generate connector images.
8
+ """
9
+
10
+ ##############################
11
+ ## GLOBAL DOCKERIGNORE FILE ##
12
+ ##############################
13
+
14
+ DOCKERIGNORE_TEMPLATE: str = "\n".join(
15
+ [
16
+ "# This file is auto-generated. Do not edit.",
17
+ # "*,"
18
+ "build/",
19
+ ".venv/",
20
+ "secrets/",
21
+ "!setup.py",
22
+ "!pyproject.toml",
23
+ "!poetry.lock",
24
+ "!poetry.toml",
25
+ "!components.py",
26
+ "!requirements.txt",
27
+ "!README.md",
28
+ "!metadata.yaml",
29
+ "!build_customization.py",
30
+ "!source_*",
31
+ "!destination_*",
32
+ ]
33
+ )
34
+
35
+ ###########################
36
+ # PYTHON CONNECTOR IMAGE ##
37
+ ###########################
38
+
39
+ PYTHON_CONNECTOR_DOCKERFILE_TEMPLATE = """
40
+ # syntax=docker/dockerfile:1
41
+ # check=skip=all
42
+ ARG BASE_IMAGE
43
+
44
+ FROM ${BASE_IMAGE} AS builder
45
+ ARG BASE_IMAGE
46
+ ARG CONNECTOR_SNAKE_NAME
47
+ ARG CONNECTOR_KEBAB_NAME
48
+ ARG EXTRA_PREREQS_SCRIPT=""
49
+
50
+ WORKDIR /airbyte/integration_code
51
+
52
+ COPY . ./
53
+
54
+ # Conditionally copy and execute the extra build script if provided
55
+ RUN if [ -n "${EXTRA_PREREQS_SCRIPT}" ]; then \
56
+ cp ${EXTRA_PREREQS_SCRIPT} ./extra_prereqs_script && \
57
+ ./extra_prereqs_script; \
58
+ fi
59
+
60
+ # TODO: Pre-install uv on the base image to speed up the build.
61
+ # (uv is still faster even with the extra step.)
62
+ RUN pip install --no-cache-dir uv
63
+ RUN python -m uv pip install --no-cache-dir .
64
+
65
+ FROM ${BASE_IMAGE}
66
+ ARG CONNECTOR_SNAKE_NAME
67
+ ARG CONNECTOR_KEBAB_NAME
68
+ ARG BASE_IMAGE
69
+
70
+ WORKDIR /airbyte/integration_code
71
+
72
+ COPY --from=builder /usr/local /usr/local
73
+ COPY --chmod=755 <<EOT /entrypoint.sh
74
+ #!/usr/bin/env bash
75
+ set -e
76
+
77
+ ${CONNECTOR_KEBAB_NAME} "\$\@"
78
+ EOT
79
+
80
+ ENV AIRBYTE_ENTRYPOINT="/entrypoint.sh"
81
+ ENTRYPOINT ["/entrypoint.sh"]
82
+ """
83
+
84
+ ##################################
85
+ # MANIFEST-ONLY CONNECTOR IMAGE ##
86
+ ##################################
87
+
88
+ MANIFEST_ONLY_DOCKERFILE_TEMPLATE = """
89
+ ARG BASE_IMAGE
90
+ ARG CONNECTOR_SNAKE_NAME
91
+ ARG CONNECTOR_KEBAB_NAME
92
+
93
+ FROM ${BASE_IMAGE}
94
+
95
+ WORKDIR /airbyte/integration_code
96
+
97
+ COPY . ./
98
+
99
+ ENV AIRBYTE_ENTRYPOINT="python ./main.py"
100
+ ENTRYPOINT ["python", "./main.py"]
101
+ """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: airbyte-cdk
3
- Version: 6.45.10
3
+ Version: 6.46.0
4
4
  Summary: A framework for writing Airbyte Connectors.
5
5
  Home-page: https://airbyte.com
6
6
  License: MIT
@@ -17,6 +17,7 @@ Classifier: Programming Language :: Python :: 3.11
17
17
  Classifier: Programming Language :: Python :: 3.12
18
18
  Classifier: Topic :: Scientific/Engineering
19
19
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
+ Provides-Extra: dev
20
21
  Provides-Extra: file-based
21
22
  Provides-Extra: sql
22
23
  Provides-Extra: vector-db-based
@@ -28,12 +29,14 @@ Requires-Dist: avro (>=1.11.2,<1.13.0) ; extra == "file-based"
28
29
  Requires-Dist: backoff
29
30
  Requires-Dist: boltons (>=25.0.0,<26.0.0)
30
31
  Requires-Dist: cachetools
32
+ Requires-Dist: click (>=8.1.8,<9.0.0)
31
33
  Requires-Dist: cohere (==4.21) ; extra == "vector-db-based"
32
34
  Requires-Dist: cryptography (>=44.0.0,<45.0.0)
33
35
  Requires-Dist: dpath (>=2.1.6,<3.0.0)
34
36
  Requires-Dist: dunamai (>=1.22.0,<2.0.0)
35
37
  Requires-Dist: fastavro (>=1.8.0,<1.9.0) ; extra == "file-based"
36
38
  Requires-Dist: genson (==1.3.0)
39
+ Requires-Dist: google-cloud-secret-manager (>=2.17.0,<3.0.0)
37
40
  Requires-Dist: isodate (>=0.6.1,<0.7.0)
38
41
  Requires-Dist: jsonref (>=0.2,<0.3)
39
42
  Requires-Dist: jsonschema (>=4.17.3,<4.18.0)
@@ -54,6 +57,7 @@ Requires-Dist: pydantic (>=2.7,<3.0)
54
57
  Requires-Dist: pyjwt (>=2.8.0,<3.0.0)
55
58
  Requires-Dist: pyrate-limiter (>=3.1.0,<3.2.0)
56
59
  Requires-Dist: pytesseract (==0.3.10) ; extra == "file-based"
60
+ Requires-Dist: pytest (>=7,<8) ; extra == "dev"
57
61
  Requires-Dist: python-calamine (==0.2.3) ; extra == "file-based"
58
62
  Requires-Dist: python-dateutil (>=2.9.0,<3.0.0)
59
63
  Requires-Dist: python-snappy (==0.7.3) ; extra == "file-based"
@@ -62,6 +66,7 @@ Requires-Dist: pytz (==2024.2)
62
66
  Requires-Dist: rapidfuzz (>=3.10.1,<4.0.0)
63
67
  Requires-Dist: requests
64
68
  Requires-Dist: requests_cache
69
+ Requires-Dist: rich-click (>=1.8.8,<2.0.0)
65
70
  Requires-Dist: serpyco-rs (>=1.10.2,<2.0.0)
66
71
  Requires-Dist: sqlalchemy (>=2.0,<3.0,!=2.0.36) ; extra == "sql"
67
72
  Requires-Dist: tiktoken (==0.8.0) ; extra == "vector-db-based"