airbyte-cdk 6.47.0.dev0__py3-none-any.whl → 6.47.2__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.
@@ -305,6 +305,7 @@ class ConcurrentDeclarativeSource(ManifestDeclarativeSource, Generic[TState]):
305
305
  stream_name=declarative_stream.name,
306
306
  stream_namespace=declarative_stream.namespace,
307
307
  config=config or {},
308
+ stream_state_migrations=declarative_stream.state_migrations,
308
309
  )
309
310
  partition_generator = StreamSlicerPartitionGenerator(
310
311
  partition_factory=DeclarativePartitionFactory(
@@ -15,7 +15,7 @@ from airbyte_cdk.sources.declarative.extractors.type_transformer import (
15
15
  )
16
16
  from airbyte_cdk.sources.declarative.interpolation import InterpolatedString
17
17
  from airbyte_cdk.sources.declarative.models import SchemaNormalization
18
- from airbyte_cdk.sources.declarative.retrievers.file_uploader import FileUploader
18
+ from airbyte_cdk.sources.declarative.retrievers.file_uploader import DefaultFileUploader
19
19
  from airbyte_cdk.sources.declarative.transformations import RecordTransformation
20
20
  from airbyte_cdk.sources.types import Config, Record, StreamSlice, StreamState
21
21
  from airbyte_cdk.sources.utils.transform import TypeTransformer
@@ -43,7 +43,7 @@ class RecordSelector(HttpSelector):
43
43
  record_filter: Optional[RecordFilter] = None
44
44
  transformations: List[RecordTransformation] = field(default_factory=lambda: [])
45
45
  transform_before_filtering: bool = False
46
- file_uploader: Optional[FileUploader] = None
46
+ file_uploader: Optional[DefaultFileUploader] = None
47
47
 
48
48
  def __post_init__(self, parameters: Mapping[str, Any]) -> None:
49
49
  self._parameters = parameters
@@ -481,7 +481,13 @@ from airbyte_cdk.sources.declarative.retrievers import (
481
481
  SimpleRetriever,
482
482
  SimpleRetrieverTestReadDecorator,
483
483
  )
484
- from airbyte_cdk.sources.declarative.retrievers.file_uploader import FileUploader
484
+ from airbyte_cdk.sources.declarative.retrievers.file_uploader import (
485
+ ConnectorBuilderFileUploader,
486
+ DefaultFileUploader,
487
+ FileUploader,
488
+ LocalFileSystemFileWriter,
489
+ NoopFileWriter,
490
+ )
485
491
  from airbyte_cdk.sources.declarative.schema import (
486
492
  ComplexFieldType,
487
493
  DefaultSchemaLoader,
@@ -2815,7 +2821,7 @@ class ModelToComponentFactory:
2815
2821
  transformations: List[RecordTransformation] | None = None,
2816
2822
  decoder: Decoder | None = None,
2817
2823
  client_side_incremental_sync: Dict[str, Any] | None = None,
2818
- file_uploader: Optional[FileUploader] = None,
2824
+ file_uploader: Optional[DefaultFileUploader] = None,
2819
2825
  **kwargs: Any,
2820
2826
  ) -> RecordSelector:
2821
2827
  extractor = self._create_component_from_model(
@@ -2919,7 +2925,7 @@ class ModelToComponentFactory:
2919
2925
  stop_condition_on_cursor: bool = False,
2920
2926
  client_side_incremental_sync: Optional[Dict[str, Any]] = None,
2921
2927
  transformations: List[RecordTransformation],
2922
- file_uploader: Optional[FileUploader] = None,
2928
+ file_uploader: Optional[DefaultFileUploader] = None,
2923
2929
  incremental_sync: Optional[
2924
2930
  Union[
2925
2931
  IncrementingCountCursorModel, DatetimeBasedCursorModel, CustomIncrementalSyncModel
@@ -3606,14 +3612,24 @@ class ModelToComponentFactory:
3606
3612
  name=name,
3607
3613
  **kwargs,
3608
3614
  )
3609
- return FileUploader(
3615
+ emit_connector_builder_messages = self._emit_connector_builder_messages
3616
+ file_uploader = DefaultFileUploader(
3610
3617
  requester=requester,
3611
3618
  download_target_extractor=download_target_extractor,
3612
3619
  config=config,
3620
+ file_writer=NoopFileWriter()
3621
+ if emit_connector_builder_messages
3622
+ else LocalFileSystemFileWriter(),
3613
3623
  parameters=model.parameters or {},
3614
3624
  filename_extractor=model.filename_extractor if model.filename_extractor else None,
3615
3625
  )
3616
3626
 
3627
+ return (
3628
+ ConnectorBuilderFileUploader(file_uploader)
3629
+ if emit_connector_builder_messages
3630
+ else file_uploader
3631
+ )
3632
+
3617
3633
  def create_moving_window_call_rate_policy(
3618
3634
  self, model: MovingWindowCallRatePolicyModel, config: Config, **kwargs: Any
3619
3635
  ) -> MovingWindowCallRatePolicy:
@@ -0,0 +1,15 @@
1
+ from .connector_builder_file_uploader import ConnectorBuilderFileUploader
2
+ from .default_file_uploader import DefaultFileUploader
3
+ from .file_uploader import FileUploader
4
+ from .file_writer import FileWriter
5
+ from .local_file_system_file_writer import LocalFileSystemFileWriter
6
+ from .noop_file_writer import NoopFileWriter
7
+
8
+ __all__ = [
9
+ "DefaultFileUploader",
10
+ "LocalFileSystemFileWriter",
11
+ "NoopFileWriter",
12
+ "ConnectorBuilderFileUploader",
13
+ "FileUploader",
14
+ "FileWriter",
15
+ ]
@@ -0,0 +1,26 @@
1
+ #
2
+ # Copyright (c) 2025 Airbyte, Inc., all rights reserved.
3
+ #
4
+
5
+ from dataclasses import dataclass
6
+
7
+ from airbyte_cdk.sources.declarative.types import Record
8
+
9
+ from .default_file_uploader import DefaultFileUploader
10
+ from .file_uploader import FileUploader
11
+
12
+
13
+ @dataclass
14
+ class ConnectorBuilderFileUploader(FileUploader):
15
+ """
16
+ Connector builder file uploader
17
+ Acts as a decorator or wrapper around a FileUploader instance, copying the attributes from record.file_reference into the record.data.
18
+ """
19
+
20
+ file_uploader: DefaultFileUploader
21
+
22
+ def upload(self, record: Record) -> None:
23
+ self.file_uploader.upload(record=record)
24
+ for file_reference_key, file_reference_value in record.file_reference.__dict__.items():
25
+ if not file_reference_key.startswith("_"):
26
+ record.data[file_reference_key] = file_reference_value # type: ignore
@@ -22,18 +22,27 @@ from airbyte_cdk.sources.declarative.types import Record, StreamSlice
22
22
  from airbyte_cdk.sources.types import Config
23
23
  from airbyte_cdk.sources.utils.files_directory import get_files_directory
24
24
 
25
+ from .file_uploader import FileUploader
26
+ from .file_writer import FileWriter
27
+
25
28
  logger = logging.getLogger("airbyte")
26
29
 
27
30
 
28
31
  @dataclass
29
- class FileUploader:
32
+ class DefaultFileUploader(FileUploader):
33
+ """
34
+ File uploader class
35
+ Handles the upload logic: fetching the download target, making the request via its requester, determining the file path, and calling self.file_writer.write()
36
+ Different types of file_writer:BaseFileWriter can be injected to handle different file writing strategies.
37
+ """
38
+
30
39
  requester: Requester
31
40
  download_target_extractor: RecordExtractor
32
41
  config: Config
42
+ file_writer: FileWriter
33
43
  parameters: InitVar[Mapping[str, Any]]
34
44
 
35
45
  filename_extractor: Optional[Union[InterpolatedString, str]] = None
36
- content_extractor: Optional[RecordExtractor] = None
37
46
 
38
47
  def __post_init__(self, parameters: Mapping[str, Any]) -> None:
39
48
  if self.filename_extractor:
@@ -61,33 +70,28 @@ class FileUploader:
61
70
  ),
62
71
  )
63
72
 
64
- if self.content_extractor:
65
- raise NotImplementedError("TODO")
66
- else:
67
- files_directory = Path(get_files_directory())
73
+ files_directory = Path(get_files_directory())
68
74
 
69
- file_name = (
70
- self.filename_extractor.eval(self.config, record=record)
71
- if self.filename_extractor
72
- else str(uuid.uuid4())
73
- )
74
- file_name = file_name.lstrip("/")
75
- file_relative_path = Path(record.stream_name) / Path(file_name)
75
+ file_name = (
76
+ self.filename_extractor.eval(self.config, record=record)
77
+ if self.filename_extractor
78
+ else str(uuid.uuid4())
79
+ )
80
+ file_name = file_name.lstrip("/")
81
+ file_relative_path = Path(record.stream_name) / Path(file_name)
76
82
 
77
- full_path = files_directory / file_relative_path
78
- full_path.parent.mkdir(parents=True, exist_ok=True)
83
+ full_path = files_directory / file_relative_path
84
+ full_path.parent.mkdir(parents=True, exist_ok=True)
79
85
 
80
- with open(str(full_path), "wb") as f:
81
- f.write(response.content)
82
- file_size_bytes = full_path.stat().st_size
86
+ file_size_bytes = self.file_writer.write(full_path, content=response.content)
83
87
 
84
- logger.info("File uploaded successfully")
85
- logger.info(f"File url: {str(full_path)}")
86
- logger.info(f"File size: {file_size_bytes / 1024} KB")
87
- logger.info(f"File relative path: {str(file_relative_path)}")
88
+ logger.info("File uploaded successfully")
89
+ logger.info(f"File url: {str(full_path)}")
90
+ logger.info(f"File size: {file_size_bytes / 1024} KB")
91
+ logger.info(f"File relative path: {str(file_relative_path)}")
88
92
 
89
- record.file_reference = AirbyteRecordMessageFileReference(
90
- staging_file_url=str(full_path),
91
- source_file_relative_path=str(file_relative_path),
92
- file_size_bytes=file_size_bytes,
93
- )
93
+ record.file_reference = AirbyteRecordMessageFileReference(
94
+ staging_file_url=str(full_path),
95
+ source_file_relative_path=str(file_relative_path),
96
+ file_size_bytes=file_size_bytes,
97
+ )
@@ -0,0 +1,22 @@
1
+ #
2
+ # Copyright (c) 2025 Airbyte, Inc., all rights reserved.
3
+ #
4
+
5
+ from abc import ABC, abstractmethod
6
+ from dataclasses import dataclass
7
+
8
+ from airbyte_cdk.sources.declarative.types import Record
9
+
10
+
11
+ @dataclass
12
+ class FileUploader(ABC):
13
+ """
14
+ Base class for file uploader
15
+ """
16
+
17
+ @abstractmethod
18
+ def upload(self, record: Record) -> None:
19
+ """
20
+ Uploads the file to the specified location
21
+ """
22
+ ...
@@ -0,0 +1,19 @@
1
+ #
2
+ # Copyright (c) 2025 Airbyte, Inc., all rights reserved.
3
+ #
4
+
5
+ from abc import ABC, abstractmethod
6
+ from pathlib import Path
7
+
8
+
9
+ class FileWriter(ABC):
10
+ """
11
+ Base File writer class
12
+ """
13
+
14
+ @abstractmethod
15
+ def write(self, file_path: Path, content: bytes) -> int:
16
+ """
17
+ Writes the file to the specified location
18
+ """
19
+ ...
@@ -0,0 +1,18 @@
1
+ #
2
+ # Copyright (c) 2025 Airbyte, Inc., all rights reserved.
3
+ #
4
+
5
+ from pathlib import Path
6
+
7
+ from .file_writer import FileWriter
8
+
9
+
10
+ class LocalFileSystemFileWriter(FileWriter):
11
+ def write(self, file_path: Path, content: bytes) -> int:
12
+ """
13
+ Writes the file to the specified location
14
+ """
15
+ with open(str(file_path), "wb") as f:
16
+ f.write(content)
17
+
18
+ return file_path.stat().st_size
@@ -0,0 +1,17 @@
1
+ #
2
+ # Copyright (c) 2025 Airbyte, Inc., all rights reserved.
3
+ #
4
+
5
+ from pathlib import Path
6
+
7
+ from .file_writer import FileWriter
8
+
9
+
10
+ class NoopFileWriter(FileWriter):
11
+ NOOP_FILE_SIZE = -1
12
+
13
+ def write(self, file_path: Path, content: bytes) -> int:
14
+ """
15
+ Noop file writer
16
+ """
17
+ return self.NOOP_FILE_SIZE
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: airbyte-cdk
3
- Version: 6.47.0.dev0
3
+ Version: 6.47.2
4
4
  Summary: A framework for writing Airbyte Connectors.
5
5
  Home-page: https://airbyte.com
6
6
  License: MIT
@@ -74,7 +74,7 @@ airbyte_cdk/sources/declarative/checks/check_stream.py,sha256=QeExVmpSYjr_CnghHu
74
74
  airbyte_cdk/sources/declarative/checks/connection_checker.py,sha256=MBRJo6WJlZQHpIfOGaNOkkHUmgUl_4wDM6VPo41z5Ss,1383
75
75
  airbyte_cdk/sources/declarative/concurrency_level/__init__.py,sha256=5XUqrmlstYlMM0j6crktlKQwALek0uiz2D3WdM46MyA,191
76
76
  airbyte_cdk/sources/declarative/concurrency_level/concurrency_level.py,sha256=YIwCTCpOr_QSNW4ltQK0yUGWInI8PKNY216HOOegYLk,2101
77
- airbyte_cdk/sources/declarative/concurrent_declarative_source.py,sha256=mB0wBAuAIvIJwRsMLoLGUoSuMimcY1tgyUjPiTHHHZE,28269
77
+ airbyte_cdk/sources/declarative/concurrent_declarative_source.py,sha256=GoZJ8Oxb3IQh6iJao6dw7NNiWVyWTrlUlWVKMWt-V0k,28362
78
78
  airbyte_cdk/sources/declarative/datetime/__init__.py,sha256=4Hw-PX1-VgESLF16cDdvuYCzGJtHntThLF4qIiULWeo,61
79
79
  airbyte_cdk/sources/declarative/datetime/datetime_parser.py,sha256=_zGNGq31RNy_0QBLt_EcTvgPyhj7urPdx6oA3M5-r3o,3150
80
80
  airbyte_cdk/sources/declarative/datetime/min_max_datetime.py,sha256=0BHBtDNQZfvwM45-tY5pNlTcKAFSGGNxemoi0Jic-0E,5785
@@ -96,7 +96,7 @@ airbyte_cdk/sources/declarative/extractors/dpath_extractor.py,sha256=wR4Ol4MG2lt
96
96
  airbyte_cdk/sources/declarative/extractors/http_selector.py,sha256=2zWZ4ewTqQC8VwkjS0xD_u350Km3SiYP7hpOOgiLg5o,1169
97
97
  airbyte_cdk/sources/declarative/extractors/record_extractor.py,sha256=XJELMjahAsaomlvQgN2zrNO0DJX0G0fr9r682gUz7Pg,691
98
98
  airbyte_cdk/sources/declarative/extractors/record_filter.py,sha256=yTdEkyDUSW2KbFkEwJJMlS963C955LgCCOVfTmmScpQ,3367
99
- airbyte_cdk/sources/declarative/extractors/record_selector.py,sha256=Xg4e0exJ5Tq8I346uD2-HjpCsAUFLgPPcNKa0UoHjV8,7178
99
+ airbyte_cdk/sources/declarative/extractors/record_selector.py,sha256=vCpwX1PVRFPYKMzm0DHHP3YEZ0Gmd3bBzggOsRha038,7192
100
100
  airbyte_cdk/sources/declarative/extractors/response_to_file_extractor.py,sha256=WJyA2OYIEgFpVP5Y3o0tIj69AV6IKkn9B16MeXaEItI,6513
101
101
  airbyte_cdk/sources/declarative/extractors/type_transformer.py,sha256=d6Y2Rfg8pMVEEnHllfVksWZdNVOU55yk34O03dP9muY,1626
102
102
  airbyte_cdk/sources/declarative/incremental/__init__.py,sha256=U1oZKtBaEC6IACmvziY9Wzg7Z8EgF4ZuR7NwvjlB_Sk,1255
@@ -128,7 +128,7 @@ airbyte_cdk/sources/declarative/parsers/custom_exceptions.py,sha256=wnRUP0Xeru9R
128
128
  airbyte_cdk/sources/declarative/parsers/manifest_component_transformer.py,sha256=RUyFZS0zslLb7UfQrvqMC--k5CVLNSp7zHw6kbosvKE,9688
129
129
  airbyte_cdk/sources/declarative/parsers/manifest_normalizer.py,sha256=laBy7ebjA-PiNwc-50U4FHvMqS_mmHvnabxgFs4CjGw,17069
130
130
  airbyte_cdk/sources/declarative/parsers/manifest_reference_resolver.py,sha256=pJmg78vqE5VfUrF_KJnWjucQ4k9IWFULeAxHCowrHXE,6806
131
- airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py,sha256=3sHQPrJrgIsk_D17g3vf61JfD4MEJDbniR1JqOyMb64,161761
131
+ airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py,sha256=JX5YAUoTGIjTxIGJoIbRoOvk2piHBNnPQDseSOQzoR0,162286
132
132
  airbyte_cdk/sources/declarative/partition_routers/__init__.py,sha256=TBC9AkGaUqHm2IKHMPN6punBIcY5tWGULowcLoAVkfw,1109
133
133
  airbyte_cdk/sources/declarative/partition_routers/async_job_partition_router.py,sha256=VelO7zKqKtzMJ35jyFeg0ypJLQC0plqqIBNXoBW1G2E,3001
134
134
  airbyte_cdk/sources/declarative/partition_routers/cartesian_product_stream_slicer.py,sha256=c5cuVFM6NFkuQqG8Z5IwkBuwDrvXZN1CunUOM_L0ezg,6892
@@ -187,7 +187,13 @@ airbyte_cdk/sources/declarative/resolvers/config_components_resolver.py,sha256=d
187
187
  airbyte_cdk/sources/declarative/resolvers/http_components_resolver.py,sha256=AiojNs8wItJFrENZBFUaDvau3sgwudO6Wkra36upSPo,4639
188
188
  airbyte_cdk/sources/declarative/retrievers/__init__.py,sha256=nQepwG_RfW53sgwvK5dLPqfCx0VjsQ83nYoPjBMAaLM,527
189
189
  airbyte_cdk/sources/declarative/retrievers/async_retriever.py,sha256=6oZtnCHm9NdDvjTSrVwPQOXGSdETSIR7eWH2vFjM7jI,4855
190
- airbyte_cdk/sources/declarative/retrievers/file_uploader.py,sha256=J-OjleRStGAGaoPylttyFQwVGHvtFTqdfnS0JYcYUtg,3537
190
+ airbyte_cdk/sources/declarative/retrievers/file_uploader/__init__.py,sha256=ovs0oZGPEEw-V4asqr0D1Xty2u7tR8ADhRuHNgXGuWQ,490
191
+ airbyte_cdk/sources/declarative/retrievers/file_uploader/connector_builder_file_uploader.py,sha256=wHGnluTJ6HVbCkSaNNQQN2t9ZzhaFGoo_pzXTz54gBY,878
192
+ airbyte_cdk/sources/declarative/retrievers/file_uploader/default_file_uploader.py,sha256=7AFJxJknE7whofFBxoBp-EUrpu2QyZh1dwEq1jb3D-I,3689
193
+ airbyte_cdk/sources/declarative/retrievers/file_uploader/file_uploader.py,sha256=bWCWQzPokZ9rWmmi3I6RfaG53FhSN5yj3JouRhtnz7E,431
194
+ airbyte_cdk/sources/declarative/retrievers/file_uploader/file_writer.py,sha256=V8gAFjQXkhX5mwj1NafdcUrMfMBNF1hi0mrdXIl5qEc,359
195
+ airbyte_cdk/sources/declarative/retrievers/file_uploader/local_file_system_file_writer.py,sha256=jLpdonre1UHfbjGSD5AK_T0codLABJByTvbqepDZtEQ,422
196
+ airbyte_cdk/sources/declarative/retrievers/file_uploader/noop_file_writer.py,sha256=1yfimzxm09d2j605cu_HhiYVDNVL1rUMi3vs_jYlIyY,330
191
197
  airbyte_cdk/sources/declarative/retrievers/retriever.py,sha256=XPLs593Xv8c5cKMc37XzUAYmzlXd1a7eSsspM-CMuWA,1696
192
198
  airbyte_cdk/sources/declarative/retrievers/simple_retriever.py,sha256=O7qpM71L1_ATIbEKa8y658jdiSJSPw0KmuGKgnaruQU,31008
193
199
  airbyte_cdk/sources/declarative/schema/__init__.py,sha256=xU45UvM5O4c1PSM13UHpCdh5hpW3HXy9vRRGEiAC1rg,795
@@ -390,9 +396,9 @@ airbyte_cdk/utils/slice_hasher.py,sha256=EDxgROHDbfG-QKQb59m7h_7crN1tRiawdf5uU7G
390
396
  airbyte_cdk/utils/spec_schema_transformations.py,sha256=-5HTuNsnDBAhj-oLeQXwpTGA0HdcjFOf2zTEMUTTg_Y,816
391
397
  airbyte_cdk/utils/stream_status_utils.py,sha256=ZmBoiy5HVbUEHAMrUONxZvxnvfV9CesmQJLDTAIWnWw,1171
392
398
  airbyte_cdk/utils/traced_exception.py,sha256=C8uIBuCL_E4WnBAOPSxBicD06JAldoN9fGsQDp463OY,6292
393
- airbyte_cdk-6.47.0.dev0.dist-info/LICENSE.txt,sha256=Wfe61S4BaGPj404v8lrAbvhjYR68SHlkzeYrg3_bbuM,1051
394
- airbyte_cdk-6.47.0.dev0.dist-info/LICENSE_SHORT,sha256=aqF6D1NcESmpn-cqsxBtszTEnHKnlsp8L4x9wAh3Nxg,55
395
- airbyte_cdk-6.47.0.dev0.dist-info/METADATA,sha256=w15gBn52dA5wRUmZ_w1t2ViE2CDJimBiS4PWfjnK2vg,6328
396
- airbyte_cdk-6.47.0.dev0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
397
- airbyte_cdk-6.47.0.dev0.dist-info/entry_points.txt,sha256=AKWbEkHfpzzk9nF9tqBUaw1MbvTM4mGtEzmZQm0ZWvM,139
398
- airbyte_cdk-6.47.0.dev0.dist-info/RECORD,,
399
+ airbyte_cdk-6.47.2.dist-info/LICENSE.txt,sha256=Wfe61S4BaGPj404v8lrAbvhjYR68SHlkzeYrg3_bbuM,1051
400
+ airbyte_cdk-6.47.2.dist-info/LICENSE_SHORT,sha256=aqF6D1NcESmpn-cqsxBtszTEnHKnlsp8L4x9wAh3Nxg,55
401
+ airbyte_cdk-6.47.2.dist-info/METADATA,sha256=hKm118q6Iw_E3CKxiCZjXAPauBtssPkRvsmRVzeomvY,6323
402
+ airbyte_cdk-6.47.2.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
403
+ airbyte_cdk-6.47.2.dist-info/entry_points.txt,sha256=AKWbEkHfpzzk9nF9tqBUaw1MbvTM4mGtEzmZQm0ZWvM,139
404
+ airbyte_cdk-6.47.2.dist-info/RECORD,,