airbyte-cdk 6.12.4.dev0__py3-none-any.whl → 6.13.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 (54) hide show
  1. airbyte_cdk/__init__.py +93 -34
  2. airbyte_cdk/cli/source_declarative_manifest/__init__.py +0 -1
  3. airbyte_cdk/models/__init__.py +10 -11
  4. airbyte_cdk/sources/declarative/async_job/job_orchestrator.py +1 -1
  5. airbyte_cdk/sources/declarative/auth/__init__.py +2 -5
  6. airbyte_cdk/sources/declarative/auth/oauth.py +27 -12
  7. airbyte_cdk/sources/declarative/concurrent_declarative_source.py +0 -57
  8. airbyte_cdk/sources/declarative/declarative_component_schema.yaml +78 -1
  9. airbyte_cdk/sources/declarative/decoders/__init__.py +21 -3
  10. airbyte_cdk/sources/declarative/decoders/composite_raw_decoder.py +97 -0
  11. airbyte_cdk/sources/declarative/extractors/__init__.py +10 -2
  12. airbyte_cdk/sources/declarative/extractors/record_filter.py +5 -3
  13. airbyte_cdk/sources/declarative/incremental/__init__.py +10 -6
  14. airbyte_cdk/sources/declarative/incremental/per_partition_cursor.py +0 -14
  15. airbyte_cdk/sources/declarative/models/declarative_component_schema.py +49 -2
  16. airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py +96 -80
  17. airbyte_cdk/sources/declarative/partition_routers/__init__.py +23 -5
  18. airbyte_cdk/sources/declarative/partition_routers/async_job_partition_router.py +65 -0
  19. airbyte_cdk/sources/declarative/requesters/error_handlers/__init__.py +19 -5
  20. airbyte_cdk/sources/declarative/requesters/error_handlers/backoff_strategies/__init__.py +3 -1
  21. airbyte_cdk/sources/declarative/requesters/paginators/__init__.py +14 -3
  22. airbyte_cdk/sources/declarative/requesters/paginators/strategies/__init__.py +9 -3
  23. airbyte_cdk/sources/declarative/requesters/paginators/strategies/offset_increment.py +3 -1
  24. airbyte_cdk/sources/declarative/requesters/paginators/strategies/stop_condition.py +4 -1
  25. airbyte_cdk/sources/declarative/requesters/request_options/__init__.py +12 -3
  26. airbyte_cdk/sources/declarative/resolvers/__init__.py +31 -8
  27. airbyte_cdk/sources/declarative/resolvers/http_components_resolver.py +20 -14
  28. airbyte_cdk/sources/declarative/retrievers/__init__.py +5 -2
  29. airbyte_cdk/sources/declarative/retrievers/async_retriever.py +9 -32
  30. airbyte_cdk/sources/declarative/retrievers/simple_retriever.py +1 -1
  31. airbyte_cdk/sources/declarative/schema/__init__.py +14 -2
  32. airbyte_cdk/sources/declarative/schema/dynamic_schema_loader.py +20 -3
  33. airbyte_cdk/sources/file_based/availability_strategy/__init__.py +9 -2
  34. airbyte_cdk/sources/file_based/discovery_policy/__init__.py +6 -2
  35. airbyte_cdk/sources/file_based/file_types/__init__.py +12 -3
  36. airbyte_cdk/sources/file_based/schema_validation_policies/__init__.py +3 -1
  37. airbyte_cdk/sources/file_based/stream/concurrent/cursor/__init__.py +5 -1
  38. airbyte_cdk/sources/message/__init__.py +7 -1
  39. airbyte_cdk/sources/streams/__init__.py +1 -1
  40. airbyte_cdk/sources/streams/checkpoint/__init__.py +2 -3
  41. airbyte_cdk/sources/streams/concurrent/cursor.py +0 -1
  42. airbyte_cdk/sources/streams/http/__init__.py +2 -2
  43. airbyte_cdk/sources/streams/http/error_handlers/__init__.py +2 -2
  44. airbyte_cdk/sources/streams/http/requests_native_auth/abstract_oauth.py +8 -3
  45. airbyte_cdk/test/mock_http/__init__.py +1 -1
  46. airbyte_cdk/test/mock_http/mocker.py +3 -1
  47. airbyte_cdk/test/mock_http/response_builder.py +1 -1
  48. airbyte_cdk/utils/__init__.py +1 -1
  49. {airbyte_cdk-6.12.4.dev0.dist-info → airbyte_cdk-6.13.0.dist-info}/METADATA +3 -3
  50. {airbyte_cdk-6.12.4.dev0.dist-info → airbyte_cdk-6.13.0.dist-info}/RECORD +53 -52
  51. {airbyte_cdk-6.12.4.dev0.dist-info → airbyte_cdk-6.13.0.dist-info}/WHEEL +1 -1
  52. airbyte_cdk/sources/declarative/incremental/concurrent_partition_cursor.py +0 -344
  53. {airbyte_cdk-6.12.4.dev0.dist-info → airbyte_cdk-6.13.0.dist-info}/LICENSE.txt +0 -0
  54. {airbyte_cdk-6.12.4.dev0.dist-info → airbyte_cdk-6.13.0.dist-info}/entry_points.txt +0 -0
@@ -2,10 +2,24 @@
2
2
  # Copyright (c) 2023 Airbyte, Inc., all rights reserved.
3
3
  #
4
4
 
5
- from airbyte_cdk.sources.declarative.requesters.error_handlers.backoff_strategy import BackoffStrategy
6
- from airbyte_cdk.sources.declarative.requesters.error_handlers.composite_error_handler import CompositeErrorHandler
7
- from airbyte_cdk.sources.declarative.requesters.error_handlers.default_error_handler import DefaultErrorHandler
5
+ from airbyte_cdk.sources.declarative.requesters.error_handlers.backoff_strategy import (
6
+ BackoffStrategy,
7
+ )
8
+ from airbyte_cdk.sources.declarative.requesters.error_handlers.composite_error_handler import (
9
+ CompositeErrorHandler,
10
+ )
11
+ from airbyte_cdk.sources.declarative.requesters.error_handlers.default_error_handler import (
12
+ DefaultErrorHandler,
13
+ )
8
14
  from airbyte_cdk.sources.declarative.requesters.error_handlers.error_handler import ErrorHandler
9
- from airbyte_cdk.sources.declarative.requesters.error_handlers.http_response_filter import HttpResponseFilter
15
+ from airbyte_cdk.sources.declarative.requesters.error_handlers.http_response_filter import (
16
+ HttpResponseFilter,
17
+ )
10
18
 
11
- __all__ = ["BackoffStrategy", "CompositeErrorHandler", "DefaultErrorHandler", "ErrorHandler", "HttpResponseFilter"]
19
+ __all__ = [
20
+ "BackoffStrategy",
21
+ "CompositeErrorHandler",
22
+ "DefaultErrorHandler",
23
+ "ErrorHandler",
24
+ "HttpResponseFilter",
25
+ ]
@@ -2,7 +2,9 @@
2
2
  # Copyright (c) 2023 Airbyte, Inc., all rights reserved.
3
3
  #
4
4
 
5
- from airbyte_cdk.sources.declarative.requesters.error_handlers.backoff_strategies.constant_backoff_strategy import ConstantBackoffStrategy
5
+ from airbyte_cdk.sources.declarative.requesters.error_handlers.backoff_strategies.constant_backoff_strategy import (
6
+ ConstantBackoffStrategy,
7
+ )
6
8
  from airbyte_cdk.sources.declarative.requesters.error_handlers.backoff_strategies.exponential_backoff_strategy import (
7
9
  ExponentialBackoffStrategy,
8
10
  )
@@ -2,9 +2,20 @@
2
2
  # Copyright (c) 2023 Airbyte, Inc., all rights reserved.
3
3
  #
4
4
 
5
- from airbyte_cdk.sources.declarative.requesters.paginators.default_paginator import DefaultPaginator, PaginatorTestReadDecorator
5
+ from airbyte_cdk.sources.declarative.requesters.paginators.default_paginator import (
6
+ DefaultPaginator,
7
+ PaginatorTestReadDecorator,
8
+ )
6
9
  from airbyte_cdk.sources.declarative.requesters.paginators.no_pagination import NoPagination
7
10
  from airbyte_cdk.sources.declarative.requesters.paginators.paginator import Paginator
8
- from airbyte_cdk.sources.declarative.requesters.paginators.strategies.pagination_strategy import PaginationStrategy
11
+ from airbyte_cdk.sources.declarative.requesters.paginators.strategies.pagination_strategy import (
12
+ PaginationStrategy,
13
+ )
9
14
 
10
- __all__ = ["DefaultPaginator", "NoPagination", "PaginationStrategy", "Paginator", "PaginatorTestReadDecorator"]
15
+ __all__ = [
16
+ "DefaultPaginator",
17
+ "NoPagination",
18
+ "PaginationStrategy",
19
+ "Paginator",
20
+ "PaginatorTestReadDecorator",
21
+ ]
@@ -2,9 +2,15 @@
2
2
  # Copyright (c) 2023 Airbyte, Inc., all rights reserved.
3
3
  #
4
4
 
5
- from airbyte_cdk.sources.declarative.requesters.paginators.strategies.cursor_pagination_strategy import CursorPaginationStrategy
6
- from airbyte_cdk.sources.declarative.requesters.paginators.strategies.offset_increment import OffsetIncrement
7
- from airbyte_cdk.sources.declarative.requesters.paginators.strategies.page_increment import PageIncrement
5
+ from airbyte_cdk.sources.declarative.requesters.paginators.strategies.cursor_pagination_strategy import (
6
+ CursorPaginationStrategy,
7
+ )
8
+ from airbyte_cdk.sources.declarative.requesters.paginators.strategies.offset_increment import (
9
+ OffsetIncrement,
10
+ )
11
+ from airbyte_cdk.sources.declarative.requesters.paginators.strategies.page_increment import (
12
+ PageIncrement,
13
+ )
8
14
  from airbyte_cdk.sources.declarative.requesters.paginators.strategies.stop_condition import (
9
15
  CursorStopCondition,
10
16
  StopConditionPaginationStrategyDecorator,
@@ -83,7 +83,9 @@ class OffsetIncrement(PaginationStrategy):
83
83
  return self._offset
84
84
 
85
85
  def reset(self, reset_value: Optional[Any] = 0) -> None:
86
- if not isinstance(reset_value, int):
86
+ if reset_value is None:
87
+ self._offset = 0
88
+ elif not isinstance(reset_value, int):
87
89
  raise ValueError(
88
90
  f"Reset value {reset_value} for OffsetIncrement pagination strategy was not an integer"
89
91
  )
@@ -53,7 +53,10 @@ class StopConditionPaginationStrategyDecorator(PaginationStrategy):
53
53
  return self._delegate.next_page_token(response, last_page_size, last_record)
54
54
 
55
55
  def reset(self, reset_value: Optional[Any] = None) -> None:
56
- self._delegate.reset(reset_value)
56
+ if reset_value:
57
+ self._delegate.reset(reset_value)
58
+ else:
59
+ self._delegate.reset()
57
60
 
58
61
  def get_page_size(self) -> Optional[int]:
59
62
  return self._delegate.get_page_size()
@@ -5,10 +5,19 @@
5
5
  from airbyte_cdk.sources.declarative.requesters.request_options.datetime_based_request_options_provider import (
6
6
  DatetimeBasedRequestOptionsProvider,
7
7
  )
8
- from airbyte_cdk.sources.declarative.requesters.request_options.default_request_options_provider import DefaultRequestOptionsProvider
8
+ from airbyte_cdk.sources.declarative.requesters.request_options.default_request_options_provider import (
9
+ DefaultRequestOptionsProvider,
10
+ )
9
11
  from airbyte_cdk.sources.declarative.requesters.request_options.interpolated_request_options_provider import (
10
12
  InterpolatedRequestOptionsProvider,
11
13
  )
12
- from airbyte_cdk.sources.declarative.requesters.request_options.request_options_provider import RequestOptionsProvider
14
+ from airbyte_cdk.sources.declarative.requesters.request_options.request_options_provider import (
15
+ RequestOptionsProvider,
16
+ )
13
17
 
14
- __all__ = ["DatetimeBasedRequestOptionsProvider", "DefaultRequestOptionsProvider", "InterpolatedRequestOptionsProvider", "RequestOptionsProvider"]
18
+ __all__ = [
19
+ "DatetimeBasedRequestOptionsProvider",
20
+ "DefaultRequestOptionsProvider",
21
+ "InterpolatedRequestOptionsProvider",
22
+ "RequestOptionsProvider",
23
+ ]
@@ -2,17 +2,40 @@
2
2
  # Copyright (c) 2024 Airbyte, Inc., all rights reserved.
3
3
  #
4
4
 
5
- from airbyte_cdk.sources.declarative.resolvers.components_resolver import ComponentsResolver, ComponentMappingDefinition, ResolvedComponentMappingDefinition
6
- from airbyte_cdk.sources.declarative.resolvers.http_components_resolver import HttpComponentsResolver
7
- from airbyte_cdk.sources.declarative.resolvers.config_components_resolver import ConfigComponentsResolver, StreamConfig
8
- from airbyte_cdk.sources.declarative.models import HttpComponentsResolver as HttpComponentsResolverModel
9
- from airbyte_cdk.sources.declarative.models import ConfigComponentsResolver as ConfigComponentsResolverModel
10
- from pydantic.v1 import BaseModel
11
5
  from typing import Mapping
12
6
 
7
+ from pydantic.v1 import BaseModel
8
+
9
+ from airbyte_cdk.sources.declarative.models import (
10
+ ConfigComponentsResolver as ConfigComponentsResolverModel,
11
+ )
12
+ from airbyte_cdk.sources.declarative.models import (
13
+ HttpComponentsResolver as HttpComponentsResolverModel,
14
+ )
15
+ from airbyte_cdk.sources.declarative.resolvers.components_resolver import (
16
+ ComponentMappingDefinition,
17
+ ComponentsResolver,
18
+ ResolvedComponentMappingDefinition,
19
+ )
20
+ from airbyte_cdk.sources.declarative.resolvers.config_components_resolver import (
21
+ ConfigComponentsResolver,
22
+ StreamConfig,
23
+ )
24
+ from airbyte_cdk.sources.declarative.resolvers.http_components_resolver import (
25
+ HttpComponentsResolver,
26
+ )
27
+
13
28
  COMPONENTS_RESOLVER_TYPE_MAPPING: Mapping[str, type[BaseModel]] = {
14
29
  "HttpComponentsResolver": HttpComponentsResolverModel,
15
- "ConfigComponentsResolver": ConfigComponentsResolverModel
30
+ "ConfigComponentsResolver": ConfigComponentsResolverModel,
16
31
  }
17
32
 
18
- __all__ = ["ComponentsResolver", "HttpComponentsResolver", "ComponentMappingDefinition", "ResolvedComponentMappingDefinition", "StreamConfig", "ConfigComponentsResolver", "COMPONENTS_RESOLVER_TYPE_MAPPING"]
33
+ __all__ = [
34
+ "ComponentsResolver",
35
+ "HttpComponentsResolver",
36
+ "ComponentMappingDefinition",
37
+ "ResolvedComponentMappingDefinition",
38
+ "StreamConfig",
39
+ "ConfigComponentsResolver",
40
+ "COMPONENTS_RESOLVER_TYPE_MAPPING",
41
+ ]
@@ -88,19 +88,25 @@ class HttpComponentsResolver(ComponentsResolver):
88
88
  """
89
89
  kwargs = {"stream_template_config": stream_template_config}
90
90
 
91
- for components_values in self.retriever.read_records({}):
92
- updated_config = deepcopy(stream_template_config)
93
- kwargs["components_values"] = components_values # type: ignore[assignment] # component_values will always be of type Mapping[str, Any]
94
-
95
- for resolved_component in self._resolved_components:
96
- valid_types = (
97
- (resolved_component.value_type,) if resolved_component.value_type else None
98
- )
99
- value = resolved_component.value.eval(
100
- self.config, valid_types=valid_types, **kwargs
101
- )
91
+ for stream_slice in self.retriever.stream_slices():
92
+ for components_values in self.retriever.read_records(
93
+ records_schema={}, stream_slice=stream_slice
94
+ ):
95
+ updated_config = deepcopy(stream_template_config)
96
+ kwargs["components_values"] = components_values # type: ignore[assignment] # component_values will always be of type Mapping[str, Any]
97
+ kwargs["stream_slice"] = stream_slice # type: ignore[assignment] # stream_slice will always be of type Mapping[str, Any]
98
+
99
+ for resolved_component in self._resolved_components:
100
+ valid_types = (
101
+ (resolved_component.value_type,) if resolved_component.value_type else None
102
+ )
103
+ value = resolved_component.value.eval(
104
+ self.config, valid_types=valid_types, **kwargs
105
+ )
102
106
 
103
- path = [path.eval(self.config, **kwargs) for path in resolved_component.field_path]
104
- dpath.set(updated_config, path, value)
107
+ path = [
108
+ path.eval(self.config, **kwargs) for path in resolved_component.field_path
109
+ ]
110
+ dpath.set(updated_config, path, value)
105
111
 
106
- yield updated_config
112
+ yield updated_config
@@ -2,8 +2,11 @@
2
2
  # Copyright (c) 2023 Airbyte, Inc., all rights reserved.
3
3
  #
4
4
 
5
- from airbyte_cdk.sources.declarative.retrievers.retriever import Retriever
6
- from airbyte_cdk.sources.declarative.retrievers.simple_retriever import SimpleRetriever, SimpleRetrieverTestReadDecorator
7
5
  from airbyte_cdk.sources.declarative.retrievers.async_retriever import AsyncRetriever
6
+ from airbyte_cdk.sources.declarative.retrievers.retriever import Retriever
7
+ from airbyte_cdk.sources.declarative.retrievers.simple_retriever import (
8
+ SimpleRetriever,
9
+ SimpleRetrieverTestReadDecorator,
10
+ )
8
11
 
9
12
  __all__ = ["Retriever", "SimpleRetriever", "SimpleRetrieverTestReadDecorator", "AsyncRetriever"]
@@ -1,8 +1,8 @@
1
1
  # Copyright (c) 2024 Airbyte, Inc., all rights reserved.
2
2
 
3
3
 
4
- from dataclasses import InitVar, dataclass, field
5
- from typing import Any, Callable, Iterable, Mapping, Optional
4
+ from dataclasses import InitVar, dataclass
5
+ from typing import Any, Iterable, Mapping, Optional
6
6
 
7
7
  from typing_extensions import deprecated
8
8
 
@@ -12,9 +12,10 @@ from airbyte_cdk.sources.declarative.async_job.job_orchestrator import (
12
12
  AsyncPartition,
13
13
  )
14
14
  from airbyte_cdk.sources.declarative.extractors.record_selector import RecordSelector
15
- from airbyte_cdk.sources.declarative.partition_routers import SinglePartitionRouter
16
- from airbyte_cdk.sources.declarative.retrievers import Retriever
17
- from airbyte_cdk.sources.declarative.stream_slicers import StreamSlicer
15
+ from airbyte_cdk.sources.declarative.partition_routers.async_job_partition_router import (
16
+ AsyncJobPartitionRouter,
17
+ )
18
+ from airbyte_cdk.sources.declarative.retrievers.retriever import Retriever
18
19
  from airbyte_cdk.sources.source import ExperimentalClassWarning
19
20
  from airbyte_cdk.sources.streams.core import StreamData
20
21
  from airbyte_cdk.sources.types import Config, StreamSlice, StreamState
@@ -29,15 +30,10 @@ from airbyte_cdk.utils.traced_exception import AirbyteTracedException
29
30
  class AsyncRetriever(Retriever):
30
31
  config: Config
31
32
  parameters: InitVar[Mapping[str, Any]]
32
- job_orchestrator_factory: Callable[[Iterable[StreamSlice]], AsyncJobOrchestrator]
33
33
  record_selector: RecordSelector
34
- stream_slicer: StreamSlicer = field(
35
- default_factory=lambda: SinglePartitionRouter(parameters={})
36
- )
34
+ stream_slicer: AsyncJobPartitionRouter
37
35
 
38
36
  def __post_init__(self, parameters: Mapping[str, Any]) -> None:
39
- self._job_orchestrator_factory = self.job_orchestrator_factory
40
- self.__job_orchestrator: Optional[AsyncJobOrchestrator] = None
41
37
  self._parameters = parameters
42
38
 
43
39
  @property
@@ -54,17 +50,6 @@ class AsyncRetriever(Retriever):
54
50
  """
55
51
  pass
56
52
 
57
- @property
58
- def _job_orchestrator(self) -> AsyncJobOrchestrator:
59
- if not self.__job_orchestrator:
60
- raise AirbyteTracedException(
61
- message="Invalid state within AsyncJobRetriever. Please contact Airbyte Support",
62
- internal_message="AsyncPartitionRepository is expected to be accessed only after `stream_slices`",
63
- failure_type=FailureType.system_error,
64
- )
65
-
66
- return self.__job_orchestrator
67
-
68
53
  def _get_stream_state(self) -> StreamState:
69
54
  """
70
55
  Gets the current state of the stream.
@@ -99,15 +84,7 @@ class AsyncRetriever(Retriever):
99
84
  return stream_slice["partition"] # type: ignore # stream_slice["partition"] has been added as an AsyncPartition as part of stream_slices
100
85
 
101
86
  def stream_slices(self) -> Iterable[Optional[StreamSlice]]:
102
- slices = self.stream_slicer.stream_slices()
103
- self.__job_orchestrator = self._job_orchestrator_factory(slices)
104
-
105
- for completed_partition in self._job_orchestrator.create_and_get_completed_partitions():
106
- yield StreamSlice(
107
- partition=dict(completed_partition.stream_slice.partition)
108
- | {"partition": completed_partition},
109
- cursor_slice=completed_partition.stream_slice.cursor_slice,
110
- )
87
+ return self.stream_slicer.stream_slices()
111
88
 
112
89
  def read_records(
113
90
  self,
@@ -116,7 +93,7 @@ class AsyncRetriever(Retriever):
116
93
  ) -> Iterable[StreamData]:
117
94
  stream_state: StreamState = self._get_stream_state()
118
95
  partition: AsyncPartition = self._validate_and_get_stream_slice_partition(stream_slice)
119
- records: Iterable[Mapping[str, Any]] = self._job_orchestrator.fetch_records(partition)
96
+ records: Iterable[Mapping[str, Any]] = self.stream_slicer.fetch_records(partition)
120
97
 
121
98
  yield from self.record_selector.filter_and_transform(
122
99
  all_data=records,
@@ -178,7 +178,7 @@ class SimpleRetriever(Retriever):
178
178
  stream_slice,
179
179
  next_page_token,
180
180
  self._paginator.get_request_headers,
181
- self.request_option_provider.get_request_headers,
181
+ self.stream_slicer.get_request_headers,
182
182
  )
183
183
  if isinstance(headers, str):
184
184
  raise ValueError("Request headers cannot be a string")
@@ -3,9 +3,21 @@
3
3
  #
4
4
 
5
5
  from airbyte_cdk.sources.declarative.schema.default_schema_loader import DefaultSchemaLoader
6
+ from airbyte_cdk.sources.declarative.schema.dynamic_schema_loader import (
7
+ DynamicSchemaLoader,
8
+ SchemaTypeIdentifier,
9
+ TypesMap,
10
+ )
6
11
  from airbyte_cdk.sources.declarative.schema.inline_schema_loader import InlineSchemaLoader
7
12
  from airbyte_cdk.sources.declarative.schema.json_file_schema_loader import JsonFileSchemaLoader
8
13
  from airbyte_cdk.sources.declarative.schema.schema_loader import SchemaLoader
9
- from airbyte_cdk.sources.declarative.schema.dynamic_schema_loader import DynamicSchemaLoader, TypesMap, SchemaTypeIdentifier
10
14
 
11
- __all__ = ["JsonFileSchemaLoader", "DefaultSchemaLoader", "SchemaLoader", "InlineSchemaLoader", "DynamicSchemaLoader", "TypesMap", "SchemaTypeIdentifier"]
15
+ __all__ = [
16
+ "JsonFileSchemaLoader",
17
+ "DefaultSchemaLoader",
18
+ "SchemaLoader",
19
+ "InlineSchemaLoader",
20
+ "DynamicSchemaLoader",
21
+ "TypesMap",
22
+ "SchemaTypeIdentifier",
23
+ ]
@@ -4,7 +4,7 @@
4
4
 
5
5
 
6
6
  from copy import deepcopy
7
- from dataclasses import InitVar, dataclass
7
+ from dataclasses import InitVar, dataclass, field
8
8
  from typing import Any, List, Mapping, MutableMapping, Optional, Union
9
9
 
10
10
  import dpath
@@ -13,8 +13,9 @@ from typing_extensions import deprecated
13
13
  from airbyte_cdk.sources.declarative.interpolation.interpolated_string import InterpolatedString
14
14
  from airbyte_cdk.sources.declarative.retrievers.retriever import Retriever
15
15
  from airbyte_cdk.sources.declarative.schema.schema_loader import SchemaLoader
16
+ from airbyte_cdk.sources.declarative.transformations import RecordTransformation
16
17
  from airbyte_cdk.sources.source import ExperimentalClassWarning
17
- from airbyte_cdk.sources.types import Config
18
+ from airbyte_cdk.sources.types import Config, StreamSlice, StreamState
18
19
 
19
20
  AIRBYTE_DATA_TYPES: Mapping[str, Mapping[str, Any]] = {
20
21
  "string": {"type": ["null", "string"]},
@@ -103,6 +104,7 @@ class DynamicSchemaLoader(SchemaLoader):
103
104
  config: Config
104
105
  parameters: InitVar[Mapping[str, Any]]
105
106
  schema_type_identifier: SchemaTypeIdentifier
107
+ schema_transformations: List[RecordTransformation] = field(default_factory=lambda: [])
106
108
 
107
109
  def get_json_schema(self) -> Mapping[str, Any]:
108
110
  """
@@ -128,12 +130,27 @@ class DynamicSchemaLoader(SchemaLoader):
128
130
  )
129
131
  properties[key] = value
130
132
 
133
+ transformed_properties = self._transform(properties, {})
134
+
131
135
  return {
132
136
  "$schema": "http://json-schema.org/draft-07/schema#",
133
137
  "type": "object",
134
- "properties": properties,
138
+ "properties": transformed_properties,
135
139
  }
136
140
 
141
+ def _transform(
142
+ self,
143
+ properties: Mapping[str, Any],
144
+ stream_state: StreamState,
145
+ stream_slice: Optional[StreamSlice] = None,
146
+ ) -> Mapping[str, Any]:
147
+ for transformation in self.schema_transformations:
148
+ transformation.transform(
149
+ properties, # type: ignore # properties has type Mapping[str, Any], but Dict[str, Any] expected
150
+ config=self.config,
151
+ )
152
+ return properties
153
+
137
154
  def _get_key(
138
155
  self,
139
156
  raw_schema: MutableMapping[str, Any],
@@ -1,4 +1,11 @@
1
- from .abstract_file_based_availability_strategy import AbstractFileBasedAvailabilityStrategy, AbstractFileBasedAvailabilityStrategyWrapper
1
+ from .abstract_file_based_availability_strategy import (
2
+ AbstractFileBasedAvailabilityStrategy,
3
+ AbstractFileBasedAvailabilityStrategyWrapper,
4
+ )
2
5
  from .default_file_based_availability_strategy import DefaultFileBasedAvailabilityStrategy
3
6
 
4
- __all__ = ["AbstractFileBasedAvailabilityStrategy", "AbstractFileBasedAvailabilityStrategyWrapper", "DefaultFileBasedAvailabilityStrategy"]
7
+ __all__ = [
8
+ "AbstractFileBasedAvailabilityStrategy",
9
+ "AbstractFileBasedAvailabilityStrategyWrapper",
10
+ "DefaultFileBasedAvailabilityStrategy",
11
+ ]
@@ -1,4 +1,8 @@
1
- from airbyte_cdk.sources.file_based.discovery_policy.abstract_discovery_policy import AbstractDiscoveryPolicy
2
- from airbyte_cdk.sources.file_based.discovery_policy.default_discovery_policy import DefaultDiscoveryPolicy
1
+ from airbyte_cdk.sources.file_based.discovery_policy.abstract_discovery_policy import (
2
+ AbstractDiscoveryPolicy,
3
+ )
4
+ from airbyte_cdk.sources.file_based.discovery_policy.default_discovery_policy import (
5
+ DefaultDiscoveryPolicy,
6
+ )
3
7
 
4
8
  __all__ = ["AbstractDiscoveryPolicy", "DefaultDiscoveryPolicy"]
@@ -1,8 +1,8 @@
1
1
  from typing import Any, Mapping, Type
2
2
 
3
3
  from airbyte_cdk.sources.file_based.config.avro_format import AvroFormat
4
- from airbyte_cdk.sources.file_based.config.excel_format import ExcelFormat
5
4
  from airbyte_cdk.sources.file_based.config.csv_format import CsvFormat
5
+ from airbyte_cdk.sources.file_based.config.excel_format import ExcelFormat
6
6
  from airbyte_cdk.sources.file_based.config.jsonl_format import JsonlFormat
7
7
  from airbyte_cdk.sources.file_based.config.parquet_format import ParquetFormat
8
8
  from airbyte_cdk.sources.file_based.config.unstructured_format import UnstructuredFormat
@@ -10,11 +10,11 @@ from airbyte_cdk.sources.file_based.config.unstructured_format import Unstructur
10
10
  from .avro_parser import AvroParser
11
11
  from .csv_parser import CsvParser
12
12
  from .excel_parser import ExcelParser
13
+ from .file_transfer import FileTransfer
13
14
  from .file_type_parser import FileTypeParser
14
15
  from .jsonl_parser import JsonlParser
15
16
  from .parquet_parser import ParquetParser
16
17
  from .unstructured_parser import UnstructuredParser
17
- from .file_transfer import FileTransfer
18
18
 
19
19
  default_parsers: Mapping[Type[Any], FileTypeParser] = {
20
20
  AvroFormat: AvroParser(),
@@ -25,4 +25,13 @@ default_parsers: Mapping[Type[Any], FileTypeParser] = {
25
25
  UnstructuredFormat: UnstructuredParser(),
26
26
  }
27
27
 
28
- __all__ = ["AvroParser", "CsvParser", "ExcelParser", "JsonlParser", "ParquetParser", "UnstructuredParser", "FileTransfer", "default_parsers"]
28
+ __all__ = [
29
+ "AvroParser",
30
+ "CsvParser",
31
+ "ExcelParser",
32
+ "JsonlParser",
33
+ "ParquetParser",
34
+ "UnstructuredParser",
35
+ "FileTransfer",
36
+ "default_parsers",
37
+ ]
@@ -1,4 +1,6 @@
1
- from airbyte_cdk.sources.file_based.schema_validation_policies.abstract_schema_validation_policy import AbstractSchemaValidationPolicy
1
+ from airbyte_cdk.sources.file_based.schema_validation_policies.abstract_schema_validation_policy import (
2
+ AbstractSchemaValidationPolicy,
3
+ )
2
4
  from airbyte_cdk.sources.file_based.schema_validation_policies.default_schema_validation_policies import (
3
5
  DEFAULT_SCHEMA_VALIDATION_POLICIES,
4
6
  EmitRecordPolicy,
@@ -2,4 +2,8 @@ from .abstract_concurrent_file_based_cursor import AbstractConcurrentFileBasedCu
2
2
  from .file_based_concurrent_cursor import FileBasedConcurrentCursor
3
3
  from .file_based_final_state_cursor import FileBasedFinalStateCursor
4
4
 
5
- __all__ = ["AbstractConcurrentFileBasedCursor", "FileBasedConcurrentCursor", "FileBasedFinalStateCursor"]
5
+ __all__ = [
6
+ "AbstractConcurrentFileBasedCursor",
7
+ "FileBasedConcurrentCursor",
8
+ "FileBasedFinalStateCursor",
9
+ ]
@@ -10,4 +10,10 @@ from .repository import (
10
10
  NoopMessageRepository,
11
11
  )
12
12
 
13
- __all__ = ["InMemoryMessageRepository", "LogAppenderMessageRepositoryDecorator", "LogMessage", "MessageRepository", "NoopMessageRepository"]
13
+ __all__ = [
14
+ "InMemoryMessageRepository",
15
+ "LogAppenderMessageRepositoryDecorator",
16
+ "LogMessage",
17
+ "MessageRepository",
18
+ "NoopMessageRepository",
19
+ ]
@@ -3,6 +3,6 @@
3
3
  #
4
4
 
5
5
  # Initialize Streams Package
6
- from .core import NO_CURSOR_STATE_KEY, IncrementalMixin, CheckpointMixin, Stream
6
+ from .core import NO_CURSOR_STATE_KEY, CheckpointMixin, IncrementalMixin, Stream
7
7
 
8
8
  __all__ = ["NO_CURSOR_STATE_KEY", "IncrementalMixin", "CheckpointMixin", "Stream"]
@@ -8,12 +8,11 @@ from .checkpoint_reader import (
8
8
  FullRefreshCheckpointReader,
9
9
  IncrementalCheckpointReader,
10
10
  LegacyCursorBasedCheckpointReader,
11
- ResumableFullRefreshCheckpointReader
11
+ ResumableFullRefreshCheckpointReader,
12
12
  )
13
13
  from .cursor import Cursor
14
14
  from .resumable_full_refresh_cursor import ResumableFullRefreshCursor
15
15
 
16
-
17
16
  __all__ = [
18
17
  "CheckpointMode",
19
18
  "CheckpointReader",
@@ -23,5 +22,5 @@ __all__ = [
23
22
  "IncrementalCheckpointReader",
24
23
  "LegacyCursorBasedCheckpointReader",
25
24
  "ResumableFullRefreshCheckpointReader",
26
- "ResumableFullRefreshCursor"
25
+ "ResumableFullRefreshCursor",
27
26
  ]
@@ -226,7 +226,6 @@ class ConcurrentCursor(Cursor):
226
226
  )
227
227
 
228
228
  def observe(self, record: Record) -> None:
229
- print(f"Observing record: {record}")
230
229
  most_recent_cursor_value = self._most_recent_cursor_value_per_partition.get(
231
230
  record.associated_slice
232
231
  )
@@ -3,8 +3,8 @@
3
3
  #
4
4
 
5
5
  # Initialize Streams Package
6
- from .http_client import HttpClient
7
- from .http import HttpStream, HttpSubStream
8
6
  from .exceptions import UserDefinedBackoffException
7
+ from .http import HttpStream, HttpSubStream
8
+ from .http_client import HttpClient
9
9
 
10
10
  __all__ = ["HttpClient", "HttpStream", "HttpSubStream", "UserDefinedBackoffException"]
@@ -8,7 +8,7 @@ from .error_handler import ErrorHandler
8
8
  from .error_message_parser import ErrorMessageParser
9
9
  from .http_status_error_handler import HttpStatusErrorHandler
10
10
  from .json_error_message_parser import JsonErrorMessageParser
11
- from .response_models import ResponseAction, ErrorResolution
11
+ from .response_models import ErrorResolution, ResponseAction
12
12
 
13
13
  __all__ = [
14
14
  "BackoffStrategy",
@@ -18,5 +18,5 @@ __all__ = [
18
18
  "HttpStatusErrorHandler",
19
19
  "JsonErrorMessageParser",
20
20
  "ResponseAction",
21
- "ErrorResolution"
21
+ "ErrorResolution",
22
22
  ]
@@ -54,7 +54,12 @@ class AbstractOauth2Authenticator(AuthBase):
54
54
 
55
55
  def get_auth_header(self) -> Mapping[str, Any]:
56
56
  """HTTP header to set on the requests"""
57
- return {"Authorization": f"Bearer {self.get_access_token()}"}
57
+ token = self.access_token if self._is_access_token_flow else self.get_access_token()
58
+ return {"Authorization": f"Bearer {token}"}
59
+
60
+ @property
61
+ def _is_access_token_flow(self) -> bool:
62
+ return self.get_token_refresh_endpoint() is None and self.access_token is not None
58
63
 
59
64
  def get_access_token(self) -> str:
60
65
  """Returns the access token"""
@@ -121,7 +126,7 @@ class AbstractOauth2Authenticator(AuthBase):
121
126
  try:
122
127
  response = requests.request(
123
128
  method="POST",
124
- url=self.get_token_refresh_endpoint(),
129
+ url=self.get_token_refresh_endpoint(), # type: ignore # returns None, if not provided, but str | bytes is expected.
125
130
  data=self.build_refresh_request_body(),
126
131
  )
127
132
  if response.ok:
@@ -198,7 +203,7 @@ class AbstractOauth2Authenticator(AuthBase):
198
203
  return None
199
204
 
200
205
  @abstractmethod
201
- def get_token_refresh_endpoint(self) -> str:
206
+ def get_token_refresh_endpoint(self) -> Optional[str]:
202
207
  """Returns the endpoint to refresh the access token"""
203
208
 
204
209
  @abstractmethod
@@ -1,6 +1,6 @@
1
1
  from airbyte_cdk.test.mock_http.matcher import HttpRequestMatcher
2
+ from airbyte_cdk.test.mock_http.mocker import HttpMocker
2
3
  from airbyte_cdk.test.mock_http.request import HttpRequest
3
4
  from airbyte_cdk.test.mock_http.response import HttpResponse
4
- from airbyte_cdk.test.mock_http.mocker import HttpMocker
5
5
 
6
6
  __all__ = ["HttpMocker", "HttpRequest", "HttpRequestMatcher", "HttpResponse"]
@@ -8,7 +8,9 @@ from typing import Callable, List, Optional, Union
8
8
 
9
9
  import requests_mock
10
10
 
11
- from airbyte_cdk.test.mock_http import HttpRequest, HttpRequestMatcher, HttpResponse
11
+ from airbyte_cdk.test.mock_http.matcher import HttpRequestMatcher
12
+ from airbyte_cdk.test.mock_http.request import HttpRequest
13
+ from airbyte_cdk.test.mock_http.response import HttpResponse
12
14
 
13
15
 
14
16
  class SupportedHttpMethods(str, Enum):
@@ -6,7 +6,7 @@ from abc import ABC, abstractmethod
6
6
  from pathlib import Path as FilePath
7
7
  from typing import Any, Dict, List, Optional, Union
8
8
 
9
- from airbyte_cdk.test.mock_http import HttpResponse
9
+ from airbyte_cdk.test.mock_http.response import HttpResponse
10
10
  from airbyte_cdk.test.utils.data import get_unit_test_folder
11
11
 
12
12