airbyte-cdk 6.8.1rc9__py3-none-any.whl → 6.8.2.dev1__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/source_declarative_manifest/_run.py +11 -5
- airbyte_cdk/config_observation.py +1 -1
- airbyte_cdk/connector_builder/main.py +1 -1
- airbyte_cdk/connector_builder/message_grouper.py +10 -10
- airbyte_cdk/destinations/destination.py +1 -1
- airbyte_cdk/destinations/vector_db_based/embedder.py +2 -2
- airbyte_cdk/destinations/vector_db_based/writer.py +12 -4
- airbyte_cdk/entrypoint.py +7 -6
- airbyte_cdk/logger.py +2 -2
- airbyte_cdk/sources/abstract_source.py +1 -1
- airbyte_cdk/sources/config.py +1 -1
- airbyte_cdk/sources/connector_state_manager.py +9 -4
- airbyte_cdk/sources/declarative/auth/oauth.py +1 -1
- airbyte_cdk/sources/declarative/auth/selective_authenticator.py +6 -1
- airbyte_cdk/sources/declarative/concurrent_declarative_source.py +76 -28
- airbyte_cdk/sources/declarative/datetime/min_max_datetime.py +10 -4
- airbyte_cdk/sources/declarative/declarative_component_schema.yaml +16 -17
- airbyte_cdk/sources/declarative/decoders/noop_decoder.py +4 -1
- airbyte_cdk/sources/declarative/extractors/record_filter.py +3 -5
- airbyte_cdk/sources/declarative/incremental/__init__.py +3 -0
- airbyte_cdk/sources/declarative/incremental/concurrent_partition_cursor.py +270 -0
- airbyte_cdk/sources/declarative/incremental/datetime_based_cursor.py +8 -6
- airbyte_cdk/sources/declarative/incremental/per_partition_cursor.py +9 -0
- airbyte_cdk/sources/declarative/interpolation/jinja.py +35 -36
- airbyte_cdk/sources/declarative/interpolation/macros.py +1 -1
- airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py +71 -17
- airbyte_cdk/sources/declarative/partition_routers/substream_partition_router.py +13 -7
- airbyte_cdk/sources/declarative/requesters/error_handlers/default_error_handler.py +1 -1
- airbyte_cdk/sources/declarative/requesters/error_handlers/http_response_filter.py +8 -6
- airbyte_cdk/sources/declarative/requesters/paginators/default_paginator.py +1 -1
- airbyte_cdk/sources/declarative/requesters/request_options/datetime_based_request_options_provider.py +2 -2
- airbyte_cdk/sources/declarative/requesters/request_options/interpolated_request_options_provider.py +1 -1
- airbyte_cdk/sources/declarative/retrievers/async_retriever.py +5 -2
- airbyte_cdk/sources/declarative/retrievers/simple_retriever.py +1 -1
- airbyte_cdk/sources/declarative/spec/spec.py +1 -1
- airbyte_cdk/sources/declarative/stream_slicers/declarative_partition_generator.py +0 -1
- airbyte_cdk/sources/embedded/base_integration.py +3 -2
- airbyte_cdk/sources/file_based/availability_strategy/abstract_file_based_availability_strategy.py +12 -4
- airbyte_cdk/sources/file_based/availability_strategy/default_file_based_availability_strategy.py +18 -7
- airbyte_cdk/sources/file_based/file_types/avro_parser.py +14 -11
- airbyte_cdk/sources/file_based/file_types/csv_parser.py +3 -3
- airbyte_cdk/sources/file_based/file_types/excel_parser.py +11 -5
- airbyte_cdk/sources/file_based/file_types/jsonl_parser.py +1 -1
- airbyte_cdk/sources/file_based/stream/abstract_file_based_stream.py +2 -2
- airbyte_cdk/sources/file_based/stream/concurrent/adapters.py +6 -3
- airbyte_cdk/sources/file_based/stream/cursor/default_file_based_cursor.py +1 -1
- airbyte_cdk/sources/http_logger.py +3 -3
- airbyte_cdk/sources/streams/concurrent/abstract_stream.py +5 -2
- airbyte_cdk/sources/streams/concurrent/adapters.py +6 -3
- airbyte_cdk/sources/streams/concurrent/availability_strategy.py +9 -3
- airbyte_cdk/sources/streams/concurrent/cursor.py +10 -1
- airbyte_cdk/sources/streams/concurrent/state_converters/datetime_stream_state_converter.py +2 -2
- airbyte_cdk/sources/streams/core.py +17 -14
- airbyte_cdk/sources/streams/http/http.py +19 -19
- airbyte_cdk/sources/streams/http/http_client.py +4 -48
- airbyte_cdk/sources/streams/http/requests_native_auth/abstract_token.py +2 -1
- airbyte_cdk/sources/streams/http/requests_native_auth/oauth.py +62 -33
- airbyte_cdk/sources/utils/record_helper.py +1 -1
- airbyte_cdk/sources/utils/schema_helpers.py +1 -1
- airbyte_cdk/sources/utils/transform.py +34 -15
- airbyte_cdk/test/entrypoint_wrapper.py +11 -6
- airbyte_cdk/test/mock_http/response_builder.py +1 -1
- airbyte_cdk/utils/airbyte_secrets_utils.py +1 -1
- airbyte_cdk/utils/event_timing.py +10 -10
- airbyte_cdk/utils/message_utils.py +4 -3
- airbyte_cdk/utils/spec_schema_transformations.py +3 -2
- airbyte_cdk/utils/traced_exception.py +14 -12
- airbyte_cdk-6.8.2.dev1.dist-info/METADATA +111 -0
- {airbyte_cdk-6.8.1rc9.dist-info → airbyte_cdk-6.8.2.dev1.dist-info}/RECORD +72 -71
- airbyte_cdk-6.8.1rc9.dist-info/METADATA +0 -307
- {airbyte_cdk-6.8.1rc9.dist-info → airbyte_cdk-6.8.2.dev1.dist-info}/LICENSE.txt +0 -0
- {airbyte_cdk-6.8.1rc9.dist-info → airbyte_cdk-6.8.2.dev1.dist-info}/WHEEL +0 -0
- {airbyte_cdk-6.8.1rc9.dist-info → airbyte_cdk-6.8.2.dev1.dist-info}/entry_points.txt +0 -0
@@ -23,7 +23,7 @@ from io import StringIO
|
|
23
23
|
from pathlib import Path
|
24
24
|
from typing import Any, List, Mapping, Optional, Union
|
25
25
|
|
26
|
-
|
26
|
+
import orjson
|
27
27
|
from pydantic import ValidationError as V2ValidationError
|
28
28
|
from serpyco_rs import SchemaValidationError
|
29
29
|
|
@@ -63,7 +63,7 @@ class EntrypointOutput:
|
|
63
63
|
@staticmethod
|
64
64
|
def _parse_message(message: str) -> AirbyteMessage:
|
65
65
|
try:
|
66
|
-
return AirbyteMessageSerializer.load(orjson.loads(message))
|
66
|
+
return AirbyteMessageSerializer.load(orjson.loads(message))
|
67
67
|
except (orjson.JSONDecodeError, SchemaValidationError):
|
68
68
|
# The platform assumes that logs that are not of AirbyteMessage format are log messages
|
69
69
|
return AirbyteMessage(
|
@@ -129,14 +129,19 @@ class EntrypointOutput:
|
|
129
129
|
return [
|
130
130
|
message
|
131
131
|
for message in self._get_message_by_types([Type.TRACE])
|
132
|
-
if message.trace.type == trace_type
|
133
|
-
]
|
132
|
+
if message.trace.type == trace_type # type: ignore[union-attr] # trace has `type`
|
133
|
+
]
|
134
134
|
|
135
135
|
def is_in_logs(self, pattern: str) -> bool:
|
136
136
|
"""Check if any log message case-insensitive matches the pattern."""
|
137
137
|
return any(
|
138
|
-
re.search(
|
139
|
-
|
138
|
+
re.search(
|
139
|
+
pattern,
|
140
|
+
entry.log.message, # type: ignore[union-attr] # log has `message`
|
141
|
+
flags=re.IGNORECASE,
|
142
|
+
)
|
143
|
+
for entry in self.logs
|
144
|
+
)
|
140
145
|
|
141
146
|
def is_not_in_logs(self, pattern: str) -> bool:
|
142
147
|
"""Check if no log message matches the case-insensitive pattern."""
|
@@ -183,7 +183,7 @@ class HttpResponseBuilder:
|
|
183
183
|
|
184
184
|
def _get_unit_test_folder(execution_folder: str) -> FilePath:
|
185
185
|
# FIXME: This function should be removed after the next CDK release to avoid breaking amazon-seller-partner test code.
|
186
|
-
return get_unit_test_folder(execution_folder)
|
186
|
+
return get_unit_test_folder(execution_folder)
|
187
187
|
|
188
188
|
|
189
189
|
def find_template(resource: str, execution_folder: str) -> Dict[str, Any]:
|
@@ -47,7 +47,7 @@ def get_secrets(
|
|
47
47
|
result = []
|
48
48
|
for path in secret_paths:
|
49
49
|
try:
|
50
|
-
result.append(dpath.get(config, path))
|
50
|
+
result.append(dpath.get(config, path)) # type: ignore # dpath expect MutableMapping but doesn't need it
|
51
51
|
except KeyError:
|
52
52
|
# Since we try to get paths to all known secrets in the spec, in the case of oneOfs, some secret fields may not be present
|
53
53
|
# In that case, a KeyError is thrown. This is expected behavior.
|
@@ -7,7 +7,7 @@ import logging
|
|
7
7
|
import time
|
8
8
|
from contextlib import contextmanager
|
9
9
|
from dataclasses import dataclass, field
|
10
|
-
from typing import Optional
|
10
|
+
from typing import Any, Generator, Literal, Optional
|
11
11
|
|
12
12
|
logger = logging.getLogger("airbyte")
|
13
13
|
|
@@ -18,13 +18,13 @@ class EventTimer:
|
|
18
18
|
Event nesting follows a LIFO pattern, so finish will apply to the last started event.
|
19
19
|
"""
|
20
20
|
|
21
|
-
def __init__(self, name):
|
21
|
+
def __init__(self, name: str) -> None:
|
22
22
|
self.name = name
|
23
|
-
self.events = {}
|
23
|
+
self.events: dict[str, Any] = {}
|
24
24
|
self.count = 0
|
25
|
-
self.stack = []
|
25
|
+
self.stack: list[Any] = []
|
26
26
|
|
27
|
-
def start_event(self, name):
|
27
|
+
def start_event(self, name: str) -> None:
|
28
28
|
"""
|
29
29
|
Start a new event and push it to the stack.
|
30
30
|
"""
|
@@ -32,7 +32,7 @@ class EventTimer:
|
|
32
32
|
self.count += 1
|
33
33
|
self.stack.insert(0, self.events[name])
|
34
34
|
|
35
|
-
def finish_event(self):
|
35
|
+
def finish_event(self) -> None:
|
36
36
|
"""
|
37
37
|
Finish the current event and pop it from the stack.
|
38
38
|
"""
|
@@ -43,7 +43,7 @@ class EventTimer:
|
|
43
43
|
else:
|
44
44
|
logger.warning(f"{self.name} finish_event called without start_event")
|
45
45
|
|
46
|
-
def report(self, order_by="name"):
|
46
|
+
def report(self, order_by: Literal["name", "duration"] = "name") -> str:
|
47
47
|
"""
|
48
48
|
:param order_by: 'name' or 'duration'
|
49
49
|
"""
|
@@ -69,15 +69,15 @@ class Event:
|
|
69
69
|
return (self.end - self.start) / 1e9
|
70
70
|
return float("+inf")
|
71
71
|
|
72
|
-
def __str__(self):
|
72
|
+
def __str__(self) -> str:
|
73
73
|
return f"{self.name} {datetime.timedelta(seconds=self.duration)}"
|
74
74
|
|
75
|
-
def finish(self):
|
75
|
+
def finish(self) -> None:
|
76
76
|
self.end = time.perf_counter_ns()
|
77
77
|
|
78
78
|
|
79
79
|
@contextmanager
|
80
|
-
def create_timer(name):
|
80
|
+
def create_timer(name: str) -> Generator[EventTimer, Any, None]:
|
81
81
|
"""
|
82
82
|
Creates a new EventTimer as a context manager to improve code readability.
|
83
83
|
"""
|
@@ -8,15 +8,16 @@ def get_stream_descriptor(message: AirbyteMessage) -> HashableStreamDescriptor:
|
|
8
8
|
match message.type:
|
9
9
|
case Type.RECORD:
|
10
10
|
return HashableStreamDescriptor(
|
11
|
-
name=message.record.stream,
|
12
|
-
|
11
|
+
name=message.record.stream, # type: ignore[union-attr] # record has `stream`
|
12
|
+
namespace=message.record.namespace, # type: ignore[union-attr] # record has `namespace`
|
13
|
+
)
|
13
14
|
case Type.STATE:
|
14
15
|
if not message.state.stream or not message.state.stream.stream_descriptor: # type: ignore[union-attr] # state has `stream`
|
15
16
|
raise ValueError(
|
16
17
|
"State message was not in per-stream state format, which is required for record counts."
|
17
18
|
)
|
18
19
|
return HashableStreamDescriptor(
|
19
|
-
name=message.state.stream.stream_descriptor.name,
|
20
|
+
name=message.state.stream.stream_descriptor.name, # type: ignore[union-attr] # state has `stream`
|
20
21
|
namespace=message.state.stream.stream_descriptor.namespace, # type: ignore[union-attr] # state has `stream`
|
21
22
|
)
|
22
23
|
case _:
|
@@ -4,11 +4,12 @@
|
|
4
4
|
|
5
5
|
import json
|
6
6
|
import re
|
7
|
+
from typing import Any
|
7
8
|
|
8
9
|
from jsonschema import RefResolver
|
9
10
|
|
10
11
|
|
11
|
-
def resolve_refs(schema: dict) -> dict:
|
12
|
+
def resolve_refs(schema: dict[str, Any]) -> dict[str, Any]:
|
12
13
|
"""
|
13
14
|
For spec schemas generated using Pydantic models, the resulting JSON schema can contain refs between object
|
14
15
|
relationships.
|
@@ -20,6 +21,6 @@ def resolve_refs(schema: dict) -> dict:
|
|
20
21
|
str_schema = str_schema.replace(
|
21
22
|
ref_block, json.dumps(json_schema_ref_resolver.resolve(ref)[1])
|
22
23
|
)
|
23
|
-
pyschema: dict = json.loads(str_schema)
|
24
|
+
pyschema: dict[str, Any] = json.loads(str_schema)
|
24
25
|
del pyschema["definitions"]
|
25
26
|
return pyschema
|
@@ -3,9 +3,9 @@
|
|
3
3
|
#
|
4
4
|
import time
|
5
5
|
import traceback
|
6
|
-
from typing import Optional
|
6
|
+
from typing import Any, Optional
|
7
7
|
|
8
|
-
|
8
|
+
import orjson
|
9
9
|
|
10
10
|
from airbyte_cdk.models import (
|
11
11
|
AirbyteConnectionStatus,
|
@@ -104,9 +104,9 @@ class AirbyteTracedException(Exception):
|
|
104
104
|
cls,
|
105
105
|
exc: BaseException,
|
106
106
|
stream_descriptor: Optional[StreamDescriptor] = None,
|
107
|
-
*args,
|
108
|
-
**kwargs,
|
109
|
-
) -> "AirbyteTracedException":
|
107
|
+
*args: Any,
|
108
|
+
**kwargs: Any,
|
109
|
+
) -> "AirbyteTracedException":
|
110
110
|
"""
|
111
111
|
Helper to create an AirbyteTracedException from an existing exception
|
112
112
|
:param exc: the exception that caused the error
|
@@ -131,13 +131,15 @@ class AirbyteTracedException(Exception):
|
|
131
131
|
"""
|
132
132
|
error_message = self.as_airbyte_message(stream_descriptor=stream_descriptor)
|
133
133
|
if error_message.trace.error.message: # type: ignore[union-attr] # AirbyteMessage with MessageType.TRACE has AirbyteTraceMessage
|
134
|
-
error_message.trace.error.message = filter_secrets(
|
134
|
+
error_message.trace.error.message = filter_secrets( # type: ignore[union-attr]
|
135
|
+
error_message.trace.error.message, # type: ignore[union-attr]
|
136
|
+
)
|
135
137
|
if error_message.trace.error.internal_message: # type: ignore[union-attr] # AirbyteMessage with MessageType.TRACE has AirbyteTraceMessage
|
136
|
-
error_message.trace.error.internal_message = filter_secrets(
|
137
|
-
error_message.trace.error.internal_message
|
138
|
-
)
|
138
|
+
error_message.trace.error.internal_message = filter_secrets( # type: ignore[union-attr] # AirbyteMessage with MessageType.TRACE has AirbyteTraceMessage
|
139
|
+
error_message.trace.error.internal_message # type: ignore[union-attr] # AirbyteMessage with MessageType.TRACE has AirbyteTraceMessage
|
140
|
+
)
|
139
141
|
if error_message.trace.error.stack_trace: # type: ignore[union-attr] # AirbyteMessage with MessageType.TRACE has AirbyteTraceMessage
|
140
|
-
error_message.trace.error.stack_trace = filter_secrets(
|
141
|
-
error_message.trace.error.stack_trace
|
142
|
-
)
|
142
|
+
error_message.trace.error.stack_trace = filter_secrets( # type: ignore[union-attr] # AirbyteMessage with MessageType.TRACE has AirbyteTraceMessage
|
143
|
+
error_message.trace.error.stack_trace # type: ignore[union-attr] # AirbyteMessage with MessageType.TRACE has AirbyteTraceMessage
|
144
|
+
)
|
143
145
|
return error_message
|
@@ -0,0 +1,111 @@
|
|
1
|
+
Metadata-Version: 2.1
|
2
|
+
Name: airbyte-cdk
|
3
|
+
Version: 6.8.2.dev1
|
4
|
+
Summary: A framework for writing Airbyte Connectors.
|
5
|
+
Home-page: https://airbyte.com
|
6
|
+
License: MIT
|
7
|
+
Keywords: airbyte,connector-development-kit,cdk
|
8
|
+
Author: Airbyte
|
9
|
+
Author-email: contact@airbyte.io
|
10
|
+
Requires-Python: >=3.10,<3.13
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
12
|
+
Classifier: Intended Audience :: Developers
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
18
|
+
Classifier: Topic :: Scientific/Engineering
|
19
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
20
|
+
Provides-Extra: file-based
|
21
|
+
Provides-Extra: sphinx-docs
|
22
|
+
Provides-Extra: sql
|
23
|
+
Provides-Extra: vector-db-based
|
24
|
+
Requires-Dist: Jinja2 (>=3.1.2,<3.2.0)
|
25
|
+
Requires-Dist: PyYAML (>=6.0.1,<7.0.0)
|
26
|
+
Requires-Dist: Sphinx (>=4.2,<4.3) ; extra == "sphinx-docs"
|
27
|
+
Requires-Dist: airbyte-protocol-models-dataclasses (>=0.14,<0.15)
|
28
|
+
Requires-Dist: avro (>=1.11.2,<1.12.0) ; extra == "file-based"
|
29
|
+
Requires-Dist: backoff
|
30
|
+
Requires-Dist: cachetools
|
31
|
+
Requires-Dist: cohere (==4.21) ; extra == "vector-db-based"
|
32
|
+
Requires-Dist: cryptography (>=42.0.5,<44.0.0)
|
33
|
+
Requires-Dist: dpath (>=2.1.6,<3.0.0)
|
34
|
+
Requires-Dist: dunamai (>=1.22.0,<2.0.0)
|
35
|
+
Requires-Dist: fastavro (>=1.8.0,<1.9.0) ; extra == "file-based"
|
36
|
+
Requires-Dist: genson (==1.3.0)
|
37
|
+
Requires-Dist: isodate (>=0.6.1,<0.7.0)
|
38
|
+
Requires-Dist: jsonref (>=0.2,<0.3)
|
39
|
+
Requires-Dist: jsonschema (>=4.17.3,<4.18.0)
|
40
|
+
Requires-Dist: langchain (==0.1.16) ; extra == "vector-db-based"
|
41
|
+
Requires-Dist: langchain_core (==0.1.42)
|
42
|
+
Requires-Dist: markdown ; extra == "file-based"
|
43
|
+
Requires-Dist: nltk (==3.9.1)
|
44
|
+
Requires-Dist: numpy (<2)
|
45
|
+
Requires-Dist: openai[embeddings] (==0.27.9) ; extra == "vector-db-based"
|
46
|
+
Requires-Dist: orjson (>=3.10.7,<4.0.0)
|
47
|
+
Requires-Dist: pandas (==2.2.2)
|
48
|
+
Requires-Dist: pdf2image (==1.16.3) ; extra == "file-based"
|
49
|
+
Requires-Dist: pdfminer.six (==20221105) ; extra == "file-based"
|
50
|
+
Requires-Dist: pendulum (<3.0.0)
|
51
|
+
Requires-Dist: psutil (==6.1.0)
|
52
|
+
Requires-Dist: pyarrow (>=15.0.0,<15.1.0) ; extra == "file-based"
|
53
|
+
Requires-Dist: pydantic (>=2.7,<3.0)
|
54
|
+
Requires-Dist: pyjwt (>=2.8.0,<3.0.0)
|
55
|
+
Requires-Dist: pyrate-limiter (>=3.1.0,<3.2.0)
|
56
|
+
Requires-Dist: pytesseract (==0.3.10) ; extra == "file-based"
|
57
|
+
Requires-Dist: python-calamine (==0.2.3) ; extra == "file-based"
|
58
|
+
Requires-Dist: python-dateutil
|
59
|
+
Requires-Dist: python-snappy (==0.7.3) ; extra == "file-based"
|
60
|
+
Requires-Dist: python-ulid (>=3.0.0,<4.0.0)
|
61
|
+
Requires-Dist: pytz (==2024.1)
|
62
|
+
Requires-Dist: rapidfuzz (>=3.10.1,<4.0.0)
|
63
|
+
Requires-Dist: requests
|
64
|
+
Requires-Dist: requests_cache
|
65
|
+
Requires-Dist: serpyco-rs (>=1.10.2,<2.0.0)
|
66
|
+
Requires-Dist: sphinx-rtd-theme (>=1.0,<1.1) ; extra == "sphinx-docs"
|
67
|
+
Requires-Dist: sqlalchemy (>=2.0,<3.0,!=2.0.36) ; extra == "sql"
|
68
|
+
Requires-Dist: tiktoken (==0.8.0) ; extra == "vector-db-based"
|
69
|
+
Requires-Dist: unstructured.pytesseract (>=0.3.12) ; extra == "file-based"
|
70
|
+
Requires-Dist: unstructured[docx,pptx] (==0.10.27) ; extra == "file-based"
|
71
|
+
Requires-Dist: wcmatch (==10.0)
|
72
|
+
Requires-Dist: xmltodict (>=0.13.0,<0.14.0)
|
73
|
+
Project-URL: Documentation, https://docs.airbyte.io/
|
74
|
+
Project-URL: Repository, https://github.com/airbytehq/airbyte-python-cdk
|
75
|
+
Description-Content-Type: text/markdown
|
76
|
+
|
77
|
+
# Airbyte Python CDK and Low-Code CDK
|
78
|
+
|
79
|
+
Airbyte Python CDK is a framework for building Airbyte API Source Connectors. It provides a set of
|
80
|
+
classes and helpers that make it easy to build a connector against an HTTP API (REST, GraphQL, etc),
|
81
|
+
or a generic Python source connector.
|
82
|
+
|
83
|
+
## Building Connectors with the CDK
|
84
|
+
|
85
|
+
If you're looking to build a connector, we highly recommend that you first
|
86
|
+
[start with the Connector Builder](https://docs.airbyte.com/connector-development/connector-builder-ui/overview).
|
87
|
+
It should be enough for 90% connectors out there. For more flexible and complex connectors, use the
|
88
|
+
[low-code CDK and `SourceDeclarativeManifest`](https://docs.airbyte.com/connector-development/config-based/low-code-cdk-overview).
|
89
|
+
|
90
|
+
For more information on building connectors, please see the [Connector Development](https://docs.airbyte.com/connector-development/) guide on [docs.airbyte.com](https://docs.airbyte.com).
|
91
|
+
|
92
|
+
## Python CDK Overview
|
93
|
+
|
94
|
+
Airbyte CDK code is within `airbyte_cdk` directory. Here's a high level overview of what's inside:
|
95
|
+
|
96
|
+
- `airbyte_cdk/connector_builder`. Internal wrapper that helps the Connector Builder platform run a declarative manifest (low-code connector). You should not use this code directly. If you need to run a `SourceDeclarativeManifest`, take a look at [`source-declarative-manifest`](https://github.com/airbytehq/airbyte/tree/master/airbyte-integrations/connectors/source-declarative-manifest) connector implementation instead.
|
97
|
+
- `airbyte_cdk/cli/source_declarative_manifest`. This module defines the `source-declarative-manifest` (aka "SDM") connector execution logic and associated CLI.
|
98
|
+
- `airbyte_cdk/destinations`. Basic Destination connector support! If you're building a Destination connector in Python, try that. Some of our vector DB destinations like `destination-pinecone` are using that code.
|
99
|
+
- `airbyte_cdk/models` expose `airbyte_protocol.models` as a part of `airbyte_cdk` package.
|
100
|
+
- `airbyte_cdk/sources/concurrent_source` is the Concurrent CDK implementation. It supports reading data from streams concurrently per slice / partition, useful for connectors with high throughput and high number of records.
|
101
|
+
- `airbyte_cdk/sources/declarative` is the low-code CDK. It works on top of Airbyte Python CDK, but provides a declarative manifest language to define streams, operations, etc. This makes it easier to build connectors without writing Python code.
|
102
|
+
- `airbyte_cdk/sources/file_based` is the CDK for file-based sources. Examples include S3, Azure, GCS, etc.
|
103
|
+
|
104
|
+
## Contributing
|
105
|
+
|
106
|
+
For instructions on how to contribute, please see our [Contributing Guide](docs/CONTRIBUTING.md).
|
107
|
+
|
108
|
+
## Release Management
|
109
|
+
|
110
|
+
Please see the [Release Management](docs/RELEASES.md) guide for information on how to perform releases and pre-releases.
|
111
|
+
|