airbyte_cdk.sources.declarative.yaml_declarative_source

 1#
 2# Copyright (c) 2023 Airbyte, Inc., all rights reserved.
 3#
 4
 5import pkgutil
 6from typing import Any, List, Mapping, Optional
 7
 8from airbyte_cdk.models import AirbyteStateMessage, ConfiguredAirbyteCatalog
 9from airbyte_cdk.sources.declarative.concurrent_declarative_source import (
10    ConcurrentDeclarativeSource,
11)
12from airbyte_cdk.sources.types import ConnectionDefinition
13from airbyte_cdk.utils.yaml_loader import safe_load_yaml
14
15
16class YamlDeclarativeSource(ConcurrentDeclarativeSource):
17    """Declarative source defined by a yaml file"""
18
19    def __init__(
20        self,
21        path_to_yaml: str,
22        debug: bool = False,
23        catalog: Optional[ConfiguredAirbyteCatalog] = None,
24        config: Optional[Mapping[str, Any]] = None,
25        state: Optional[List[AirbyteStateMessage]] = None,
26        config_path: Optional[str] = None,
27    ) -> None:
28        """
29        :param path_to_yaml: Path to the yaml file describing the source
30        """
31        self._path_to_yaml = path_to_yaml
32        source_config = self._read_and_parse_yaml_file(path_to_yaml)
33
34        super().__init__(
35            catalog=catalog or ConfiguredAirbyteCatalog(streams=[]),
36            config=config or {},
37            state=state or [],
38            source_config=source_config,
39            config_path=config_path,
40        )
41
42    def _read_and_parse_yaml_file(self, path_to_yaml_file: str) -> ConnectionDefinition:
43        try:
44            # For testing purposes, we want to allow to just pass a file
45            with open(path_to_yaml_file, "r") as f:
46                return safe_load_yaml(f)  # type: ignore  # we assume the yaml represents a ConnectionDefinition
47        except FileNotFoundError:
48            # Running inside the container, the working directory during an operation is not structured the same as the static files
49            package = self.__class__.__module__.split(".")[0]
50
51            yaml_config = pkgutil.get_data(package, path_to_yaml_file)
52            if yaml_config:
53                decoded_yaml = yaml_config.decode()
54                return self._parse(decoded_yaml)
55            return {}
56
57    def _emit_manifest_debug_message(self, extra_args: dict[str, Any]) -> None:
58        extra_args["path_to_yaml"] = self._path_to_yaml
59
60    @staticmethod
61    def _parse(connection_definition_str: str) -> ConnectionDefinition:
62        """
63        Parses a yaml file into a manifest. Component references still exist in the manifest which will be
64        resolved during the creating of the DeclarativeSource.
65        :param connection_definition_str: yaml string to parse
66        :return: The ConnectionDefinition parsed from connection_definition_str
67        """
68        return safe_load_yaml(connection_definition_str)  # type: ignore # safe_load_yaml doesn't return a type but know it is a Mapping
17class YamlDeclarativeSource(ConcurrentDeclarativeSource):
18    """Declarative source defined by a yaml file"""
19
20    def __init__(
21        self,
22        path_to_yaml: str,
23        debug: bool = False,
24        catalog: Optional[ConfiguredAirbyteCatalog] = None,
25        config: Optional[Mapping[str, Any]] = None,
26        state: Optional[List[AirbyteStateMessage]] = None,
27        config_path: Optional[str] = None,
28    ) -> None:
29        """
30        :param path_to_yaml: Path to the yaml file describing the source
31        """
32        self._path_to_yaml = path_to_yaml
33        source_config = self._read_and_parse_yaml_file(path_to_yaml)
34
35        super().__init__(
36            catalog=catalog or ConfiguredAirbyteCatalog(streams=[]),
37            config=config or {},
38            state=state or [],
39            source_config=source_config,
40            config_path=config_path,
41        )
42
43    def _read_and_parse_yaml_file(self, path_to_yaml_file: str) -> ConnectionDefinition:
44        try:
45            # For testing purposes, we want to allow to just pass a file
46            with open(path_to_yaml_file, "r") as f:
47                return safe_load_yaml(f)  # type: ignore  # we assume the yaml represents a ConnectionDefinition
48        except FileNotFoundError:
49            # Running inside the container, the working directory during an operation is not structured the same as the static files
50            package = self.__class__.__module__.split(".")[0]
51
52            yaml_config = pkgutil.get_data(package, path_to_yaml_file)
53            if yaml_config:
54                decoded_yaml = yaml_config.decode()
55                return self._parse(decoded_yaml)
56            return {}
57
58    def _emit_manifest_debug_message(self, extra_args: dict[str, Any]) -> None:
59        extra_args["path_to_yaml"] = self._path_to_yaml
60
61    @staticmethod
62    def _parse(connection_definition_str: str) -> ConnectionDefinition:
63        """
64        Parses a yaml file into a manifest. Component references still exist in the manifest which will be
65        resolved during the creating of the DeclarativeSource.
66        :param connection_definition_str: yaml string to parse
67        :return: The ConnectionDefinition parsed from connection_definition_str
68        """
69        return safe_load_yaml(connection_definition_str)  # type: ignore # safe_load_yaml doesn't return a type but know it is a Mapping

Declarative source defined by a yaml file

YamlDeclarativeSource( path_to_yaml: str, debug: bool = False, catalog: Optional[airbyte_protocol_dataclasses.models.airbyte_protocol.ConfiguredAirbyteCatalog] = None, config: Optional[Mapping[str, Any]] = None, state: Optional[List[airbyte_cdk.models.airbyte_protocol.AirbyteStateMessage]] = None, config_path: Optional[str] = None)
20    def __init__(
21        self,
22        path_to_yaml: str,
23        debug: bool = False,
24        catalog: Optional[ConfiguredAirbyteCatalog] = None,
25        config: Optional[Mapping[str, Any]] = None,
26        state: Optional[List[AirbyteStateMessage]] = None,
27        config_path: Optional[str] = None,
28    ) -> None:
29        """
30        :param path_to_yaml: Path to the yaml file describing the source
31        """
32        self._path_to_yaml = path_to_yaml
33        source_config = self._read_and_parse_yaml_file(path_to_yaml)
34
35        super().__init__(
36            catalog=catalog or ConfiguredAirbyteCatalog(streams=[]),
37            config=config or {},
38            state=state or [],
39            source_config=source_config,
40            config_path=config_path,
41        )
Parameters
  • path_to_yaml: Path to the yaml file describing the source