airbyte-cdk 0.40.2__tar.gz → 0.40.4__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/PKG-INFO +1 -1
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/config_observation.py +10 -2
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/connector_builder/message_grouper.py +7 -2
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/connector_builder/models.py +1 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/entrypoint.py +34 -19
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/abstract_source.py +13 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/declarative_component_schema.yaml +61 -3
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/manifest_declarative_source.py +6 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/models/declarative_component_schema.py +4 -4
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py +7 -2
- airbyte-cdk-0.40.4/airbyte_cdk/sources/message/__init__.py +7 -0
- airbyte-cdk-0.40.4/airbyte_cdk/sources/message/repository.py +36 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/streams/http/requests_native_auth/abstract_oauth.py +6 -1
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/streams/http/requests_native_auth/oauth.py +9 -2
- airbyte-cdk-0.40.4/airbyte_cdk/utils/datetime_format_inferrer.py +80 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk.egg-info/PKG-INFO +1 -1
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk.egg-info/SOURCES.txt +6 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/setup.py +1 -1
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/connector_builder/test_connector_builder_handler.py +37 -3
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/connector_builder/test_message_grouper.py +8 -18
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/auth/test_oauth.py +3 -3
- airbyte-cdk-0.40.4/unit_tests/sources/message/test_repository.py +65 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/streams/http/requests_native_auth/test_requests_native_auth.py +30 -4
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/test_abstract_source.py +47 -1
- airbyte-cdk-0.40.4/unit_tests/utils/__init__.py +0 -0
- airbyte-cdk-0.40.4/unit_tests/utils/test_datetime_format_inferrer.py +53 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/LICENSE.txt +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/README.md +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/connector.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/connector_builder/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/connector_builder/connector_builder_handler.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/connector_builder/main.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/destinations/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/destinations/destination.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/exception_handler.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/logger.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/models/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/models/airbyte_protocol.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/models/well_known_types.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/py.typed +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/config.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/connector_state_manager.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/auth/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/auth/declarative_authenticator.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/auth/oauth.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/auth/token.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/checks/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/checks/check_stream.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/checks/connection_checker.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/create_partial.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/datetime/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/datetime/datetime_parser.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/datetime/min_max_datetime.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/declarative_source.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/declarative_stream.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/decoders/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/decoders/decoder.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/decoders/json_decoder.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/exceptions.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/extractors/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/extractors/dpath_extractor.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/extractors/http_selector.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/extractors/record_extractor.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/extractors/record_filter.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/extractors/record_selector.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/incremental/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/incremental/datetime_based_cursor.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/interpolation/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/interpolation/filters.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/interpolation/interpolated_boolean.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/interpolation/interpolated_mapping.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/interpolation/interpolated_nested_mapping.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/interpolation/interpolated_string.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/interpolation/interpolation.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/interpolation/jinja.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/interpolation/macros.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/models/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/parsers/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/parsers/class_types_registry.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/parsers/custom_exceptions.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/parsers/default_implementation_registry.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/parsers/manifest_component_transformer.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/parsers/manifest_reference_resolver.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/partition_routers/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/partition_routers/list_partition_router.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/partition_routers/single_partition_router.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/partition_routers/substream_partition_router.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/requesters/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/requesters/error_handlers/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/requesters/error_handlers/backoff_strategies/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/requesters/error_handlers/backoff_strategies/constant_backoff_strategy.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/requesters/error_handlers/backoff_strategies/exponential_backoff_strategy.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/requesters/error_handlers/backoff_strategies/header_helper.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/requesters/error_handlers/backoff_strategies/wait_time_from_header_backoff_strategy.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/requesters/error_handlers/backoff_strategies/wait_until_time_from_header_backoff_strategy.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/requesters/error_handlers/backoff_strategy.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/requesters/error_handlers/composite_error_handler.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/requesters/error_handlers/default_error_handler.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/requesters/error_handlers/error_handler.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/requesters/error_handlers/http_response_filter.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/requesters/error_handlers/response_action.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/requesters/error_handlers/response_status.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/requesters/http_requester.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/requesters/paginators/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/requesters/paginators/default_paginator.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/requesters/paginators/no_pagination.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/requesters/paginators/paginator.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/requesters/paginators/strategies/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/requesters/paginators/strategies/cursor_pagination_strategy.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/requesters/paginators/strategies/offset_increment.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/requesters/paginators/strategies/page_increment.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/requesters/paginators/strategies/pagination_strategy.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/requesters/request_option.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/requesters/request_options/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/requesters/request_options/interpolated_nested_request_input_provider.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/requesters/request_options/interpolated_request_input_provider.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/requesters/request_options/interpolated_request_options_provider.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/requesters/request_options/request_options_provider.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/requesters/request_path.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/requesters/requester.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/retrievers/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/retrievers/retriever.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/retrievers/simple_retriever.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/schema/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/schema/default_schema_loader.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/schema/inline_schema_loader.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/schema/json_file_schema_loader.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/schema/schema_loader.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/spec/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/spec/spec.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/stream_slicers/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/stream_slicers/cartesian_product_stream_slicer.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/stream_slicers/stream_slicer.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/transformations/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/transformations/add_fields.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/transformations/remove_fields.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/transformations/transformation.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/types.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/declarative/yaml_declarative_source.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/deprecated/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/deprecated/base_source.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/deprecated/client.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/singer/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/singer/singer_helpers.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/singer/source.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/source.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/streams/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/streams/availability_strategy.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/streams/core.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/streams/http/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/streams/http/auth/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/streams/http/auth/core.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/streams/http/auth/oauth.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/streams/http/auth/token.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/streams/http/availability_strategy.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/streams/http/exceptions.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/streams/http/http.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/streams/http/rate_limiting.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/streams/http/requests_native_auth/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/streams/http/requests_native_auth/abstract_token.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/streams/http/requests_native_auth/token.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/streams/utils/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/streams/utils/stream_helper.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/utils/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/utils/casing.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/utils/catalog_helpers.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/utils/record_helper.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/utils/schema_helpers.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/utils/schema_models.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/sources/utils/transform.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/utils/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/utils/airbyte_secrets_utils.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/utils/event_timing.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/utils/schema_inferrer.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/utils/stream_status_utils.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk/utils/traced_exception.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk.egg-info/dependency_links.txt +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk.egg-info/requires.txt +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/airbyte_cdk.egg-info/top_level.txt +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/pyproject.toml +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/setup.cfg +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/source_declarative_manifest/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/source_declarative_manifest/main.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/connector_builder/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/connector_builder/utils.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/destinations/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/destinations/test_destination.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/singer/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/singer/test_singer_helpers.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/singer/test_singer_source.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/auth/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/auth/test_session_token_auth.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/auth/test_token_auth.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/checks/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/checks/test_check_stream.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/decoders/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/decoders/test_json_decoder.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/external_component.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/extractors/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/extractors/test_dpath_extractor.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/extractors/test_record_filter.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/extractors/test_record_selector.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/incremental/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/incremental/test_datetime_based_cursor.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/interpolation/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/interpolation/test_filters.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/interpolation/test_interpolated_boolean.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/interpolation/test_interpolated_mapping.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/interpolation/test_interpolated_nested_mapping.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/interpolation/test_interpolated_string.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/interpolation/test_jinja.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/interpolation/test_macros.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/parsers/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/parsers/test_manifest_component_transformer.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/parsers/test_manifest_reference_resolver.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/parsers/test_model_to_component_factory.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/parsers/testing_components.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/partition_routers/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/partition_routers/test_list_partition_router.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/partition_routers/test_single_partition_router.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/partition_routers/test_substream_partition_router.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/requesters/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/requesters/error_handlers/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/requesters/error_handlers/backoff_strategies/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/requesters/error_handlers/backoff_strategies/test_constant_backoff.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/requesters/error_handlers/backoff_strategies/test_exponential_backoff.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/requesters/error_handlers/backoff_strategies/test_header_helper.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/requesters/error_handlers/backoff_strategies/test_wait_time_from_header.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/requesters/error_handlers/backoff_strategies/test_wait_until_time_from_header.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/requesters/error_handlers/test_composite_error_handler.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/requesters/error_handlers/test_default_error_handler.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/requesters/error_handlers/test_http_response_filter.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/requesters/error_handlers/test_response_status.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/requesters/paginators/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/requesters/paginators/test_cursor_pagination_strategy.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/requesters/paginators/test_default_paginator.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/requesters/paginators/test_no_paginator.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/requesters/paginators/test_offset_increment.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/requesters/paginators/test_page_increment.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/requesters/paginators/test_request_option.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/requesters/request_options/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/requesters/request_options/test_interpolated_request_options_provider.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/requesters/test_http_requester.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/requesters/test_interpolated_request_input_provider.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/retrievers/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/retrievers/test_simple_retriever.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/schema/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/schema/source_test/SourceTest.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/schema/source_test/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/schema/test_default_schema_loader.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/schema/test_inline_schema_loader.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/schema/test_json_file_schema_loader.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/states/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/stream_slicers/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/stream_slicers/test_cartesian_product_stream_slicer.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/test_create_partial.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/test_declarative_stream.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/test_manifest_declarative_source.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/declarative/test_yaml_declarative_source.py +0 -0
- {airbyte-cdk-0.40.2/unit_tests/sources/streams → airbyte-cdk-0.40.4/unit_tests/sources/message}/__init__.py +0 -0
- {airbyte-cdk-0.40.2/unit_tests/sources/streams/http → airbyte-cdk-0.40.4/unit_tests/sources/streams}/__init__.py +0 -0
- {airbyte-cdk-0.40.2/unit_tests/sources/streams/http/auth → airbyte-cdk-0.40.4/unit_tests/sources/streams/http}/__init__.py +0 -0
- {airbyte-cdk-0.40.2/unit_tests/sources/streams/http/requests_native_auth → airbyte-cdk-0.40.4/unit_tests/sources/streams/http/auth}/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/streams/http/auth/test_auth.py +0 -0
- {airbyte-cdk-0.40.2/unit_tests/utils → airbyte-cdk-0.40.4/unit_tests/sources/streams/http/requests_native_auth}/__init__.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/streams/http/test_availability_strategy.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/streams/http/test_http.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/streams/test_availability_strategy.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/streams/test_streams_core.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/test_config.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/test_connector_state_manager.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/sources/test_source.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/utils/test_schema_inferrer.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/utils/test_secret_utils.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/utils/test_stream_status_utils.py +0 -0
- {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.4}/unit_tests/utils/test_traced_exception.py +0 -0
@@ -68,10 +68,18 @@ def observe_connector_config(non_observed_connector_config: MutableMapping[str,
|
|
68
68
|
|
69
69
|
|
70
70
|
def emit_configuration_as_airbyte_control_message(config: MutableMapping):
|
71
|
+
"""
|
72
|
+
WARNING: deprecated - emit_configuration_as_airbyte_control_message is being deprecated in favor of the MessageRepository mechanism.
|
73
|
+
See the airbyte_cdk.sources.message package
|
74
|
+
"""
|
75
|
+
airbyte_message = create_connector_config_control_message(config)
|
76
|
+
print(airbyte_message.json(exclude_unset=True))
|
77
|
+
|
78
|
+
|
79
|
+
def create_connector_config_control_message(config):
|
71
80
|
control_message = AirbyteControlMessage(
|
72
81
|
type=OrchestratorType.CONNECTOR_CONFIG,
|
73
82
|
emitted_at=time.time() * 1000,
|
74
83
|
connectorConfig=AirbyteControlConnectorConfigMessage(config=config),
|
75
84
|
)
|
76
|
-
|
77
|
-
print(airbyte_message.json(exclude_unset=True))
|
85
|
+
return AirbyteMessage(type=Type.CONTROL, control=control_message)
|
@@ -14,6 +14,7 @@ from airbyte_cdk.entrypoint import AirbyteEntrypoint
|
|
14
14
|
from airbyte_cdk.sources import AbstractSource
|
15
15
|
from airbyte_cdk.sources.declarative.declarative_source import DeclarativeSource
|
16
16
|
from airbyte_cdk.utils import AirbyteTracedException
|
17
|
+
from airbyte_cdk.utils.datetime_format_inferrer import DatetimeFormatInferrer
|
17
18
|
from airbyte_cdk.utils.schema_inferrer import SchemaInferrer
|
18
19
|
from airbyte_protocol.models.airbyte_protocol import (
|
19
20
|
AirbyteControlMessage,
|
@@ -46,6 +47,7 @@ class MessageGrouper:
|
|
46
47
|
if record_limit is not None and not (1 <= record_limit <= 1000):
|
47
48
|
raise ValueError(f"Record limit must be between 1 and 1000. Got {record_limit}")
|
48
49
|
schema_inferrer = SchemaInferrer()
|
50
|
+
datetime_format_inferrer = DatetimeFormatInferrer()
|
49
51
|
|
50
52
|
if record_limit is None:
|
51
53
|
record_limit = self._max_record_limit
|
@@ -58,6 +60,7 @@ class MessageGrouper:
|
|
58
60
|
for message_group in self._get_message_groups(
|
59
61
|
self._read_stream(source, config, configured_catalog),
|
60
62
|
schema_inferrer,
|
63
|
+
datetime_format_inferrer,
|
61
64
|
record_limit,
|
62
65
|
):
|
63
66
|
if isinstance(message_group, AirbyteLogMessage):
|
@@ -79,11 +82,12 @@ class MessageGrouper:
|
|
79
82
|
inferred_schema=schema_inferrer.get_stream_schema(
|
80
83
|
configured_catalog.streams[0].stream.name
|
81
84
|
), # The connector builder currently only supports reading from a single stream at a time
|
82
|
-
latest_config_update=latest_config_update.connectorConfig.config if latest_config_update else
|
85
|
+
latest_config_update=self._clean_config(latest_config_update.connectorConfig.config) if latest_config_update else None,
|
86
|
+
inferred_datetime_formats=datetime_format_inferrer.get_inferred_datetime_formats(),
|
83
87
|
)
|
84
88
|
|
85
89
|
def _get_message_groups(
|
86
|
-
self, messages: Iterator[AirbyteMessage], schema_inferrer: SchemaInferrer, limit: int
|
90
|
+
self, messages: Iterator[AirbyteMessage], schema_inferrer: SchemaInferrer, datetime_format_inferrer: DatetimeFormatInferrer, limit: int
|
87
91
|
) -> Iterable[Union[StreamReadPages, AirbyteControlMessage, AirbyteLogMessage, AirbyteTraceMessage]]:
|
88
92
|
"""
|
89
93
|
Message groups are partitioned according to when request log messages are received. Subsequent response log messages
|
@@ -141,6 +145,7 @@ class MessageGrouper:
|
|
141
145
|
current_page_records.append(message.record.data)
|
142
146
|
records_count += 1
|
143
147
|
schema_inferrer.accumulate(message.record)
|
148
|
+
datetime_format_inferrer.accumulate(message.record)
|
144
149
|
elif message.type == MessageType.CONTROL and message.control.type == OrchestratorType.CONNECTOR_CONFIG:
|
145
150
|
yield message.control
|
146
151
|
else:
|
@@ -77,27 +77,32 @@ class AirbyteEntrypoint(object):
|
|
77
77
|
else:
|
78
78
|
self.logger.setLevel(logging.INFO)
|
79
79
|
|
80
|
-
# todo: add try catch for exceptions with different exit codes
|
81
80
|
source_spec: ConnectorSpecification = self.source.spec(self.logger)
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
if cmd == "check":
|
91
|
-
yield from map(AirbyteEntrypoint.airbyte_message_to_string, self.check(source_spec, config))
|
92
|
-
elif cmd == "discover":
|
93
|
-
yield from map(AirbyteEntrypoint.airbyte_message_to_string, self.discover(source_spec, config))
|
94
|
-
elif cmd == "read":
|
95
|
-
config_catalog = self.source.read_catalog(parsed_args.catalog)
|
96
|
-
state = self.source.read_state(parsed_args.state)
|
97
|
-
|
98
|
-
yield from map(AirbyteEntrypoint.airbyte_message_to_string, self.read(source_spec, config, config_catalog, state))
|
81
|
+
try:
|
82
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
83
|
+
if cmd == "spec":
|
84
|
+
message = AirbyteMessage(type=Type.SPEC, spec=source_spec)
|
85
|
+
yield from [
|
86
|
+
self.airbyte_message_to_string(queued_message) for queued_message in self._emit_queued_messages(self.source)
|
87
|
+
]
|
88
|
+
yield self.airbyte_message_to_string(message)
|
99
89
|
else:
|
100
|
-
|
90
|
+
raw_config = self.source.read_config(parsed_args.config)
|
91
|
+
config = self.source.configure(raw_config, temp_dir)
|
92
|
+
|
93
|
+
if cmd == "check":
|
94
|
+
yield from map(AirbyteEntrypoint.airbyte_message_to_string, self.check(source_spec, config))
|
95
|
+
elif cmd == "discover":
|
96
|
+
yield from map(AirbyteEntrypoint.airbyte_message_to_string, self.discover(source_spec, config))
|
97
|
+
elif cmd == "read":
|
98
|
+
config_catalog = self.source.read_catalog(parsed_args.catalog)
|
99
|
+
state = self.source.read_state(parsed_args.state)
|
100
|
+
|
101
|
+
yield from map(AirbyteEntrypoint.airbyte_message_to_string, self.read(source_spec, config, config_catalog, state))
|
102
|
+
else:
|
103
|
+
raise Exception("Unexpected command " + cmd)
|
104
|
+
finally:
|
105
|
+
yield from [self.airbyte_message_to_string(queued_message) for queued_message in self._emit_queued_messages(self.source)]
|
101
106
|
|
102
107
|
def check(self, source_spec: ConnectorSpecification, config: TConfig) -> Iterable[AirbyteMessage]:
|
103
108
|
self.set_up_secret_filter(config, source_spec.connectionSpecification)
|
@@ -106,6 +111,7 @@ class AirbyteEntrypoint(object):
|
|
106
111
|
except AirbyteTracedException as traced_exc:
|
107
112
|
connection_status = traced_exc.as_connection_status_message()
|
108
113
|
if connection_status:
|
114
|
+
yield from self._emit_queued_messages(self.source)
|
109
115
|
yield connection_status
|
110
116
|
return
|
111
117
|
|
@@ -115,6 +121,7 @@ class AirbyteEntrypoint(object):
|
|
115
121
|
else:
|
116
122
|
self.logger.error("Check failed")
|
117
123
|
|
124
|
+
yield from self._emit_queued_messages(self.source)
|
118
125
|
yield AirbyteMessage(type=Type.CONNECTION_STATUS, connectionStatus=check_result)
|
119
126
|
|
120
127
|
def discover(self, source_spec: ConnectorSpecification, config: TConfig) -> Iterable[AirbyteMessage]:
|
@@ -122,6 +129,8 @@ class AirbyteEntrypoint(object):
|
|
122
129
|
if self.source.check_config_against_spec:
|
123
130
|
self.validate_connection(source_spec, config)
|
124
131
|
catalog = self.source.discover(self.logger, config)
|
132
|
+
|
133
|
+
yield from self._emit_queued_messages(self.source)
|
125
134
|
yield AirbyteMessage(type=Type.CATALOG, catalog=catalog)
|
126
135
|
|
127
136
|
def read(self, source_spec: ConnectorSpecification, config: TConfig, catalog: TCatalog, state: TState) -> Iterable[AirbyteMessage]:
|
@@ -130,6 +139,7 @@ class AirbyteEntrypoint(object):
|
|
130
139
|
self.validate_connection(source_spec, config)
|
131
140
|
|
132
141
|
yield from self.source.read(self.logger, config, catalog, state)
|
142
|
+
yield from self._emit_queued_messages(self.source)
|
133
143
|
|
134
144
|
@staticmethod
|
135
145
|
def validate_connection(source_spec: ConnectorSpecification, config: Mapping[str, Any]) -> None:
|
@@ -149,6 +159,11 @@ class AirbyteEntrypoint(object):
|
|
149
159
|
def airbyte_message_to_string(airbyte_message: AirbyteMessage) -> str:
|
150
160
|
return airbyte_message.json(exclude_unset=True)
|
151
161
|
|
162
|
+
def _emit_queued_messages(self, source) -> Iterable[AirbyteMessage]:
|
163
|
+
if hasattr(source, "message_repository") and source.message_repository:
|
164
|
+
yield from source.message_repository.consume_queue()
|
165
|
+
return
|
166
|
+
|
152
167
|
|
153
168
|
def launch(source: Source, args: List[str]):
|
154
169
|
source_entrypoint = AirbyteEntrypoint(source)
|
@@ -22,6 +22,7 @@ from airbyte_cdk.models import (
|
|
22
22
|
)
|
23
23
|
from airbyte_cdk.models import Type as MessageType
|
24
24
|
from airbyte_cdk.sources.connector_state_manager import ConnectorStateManager
|
25
|
+
from airbyte_cdk.sources.message import MessageRepository
|
25
26
|
from airbyte_cdk.sources.source import Source
|
26
27
|
from airbyte_cdk.sources.streams import Stream
|
27
28
|
from airbyte_cdk.sources.streams.core import StreamData
|
@@ -130,6 +131,7 @@ class AbstractSource(Source, ABC):
|
|
130
131
|
yield stream_status_as_airbyte_message(configured_stream, AirbyteStreamStatus.INCOMPLETE)
|
131
132
|
raise e
|
132
133
|
except Exception as e:
|
134
|
+
yield from self._emit_queued_messages()
|
133
135
|
logger.exception(f"Encountered an exception while reading stream {configured_stream.stream.name}")
|
134
136
|
logger.info(f"Marking stream {configured_stream.stream.name} as STOPPED")
|
135
137
|
yield stream_status_as_airbyte_message(configured_stream, AirbyteStreamStatus.INCOMPLETE)
|
@@ -198,6 +200,7 @@ class AbstractSource(Source, ABC):
|
|
198
200
|
logger.info(f"Marking stream {stream_name} as RUNNING")
|
199
201
|
# If we just read the first record of the stream, emit the transition to the RUNNING state
|
200
202
|
yield stream_status_as_airbyte_message(configured_stream, AirbyteStreamStatus.RUNNING)
|
203
|
+
yield from self._emit_queued_messages()
|
201
204
|
yield record
|
202
205
|
|
203
206
|
logger.info(f"Read {record_counter} records from {stream_name} stream")
|
@@ -264,6 +267,7 @@ class AbstractSource(Source, ABC):
|
|
264
267
|
record_counter = 0
|
265
268
|
for message_counter, record_data_or_message in enumerate(records, start=1):
|
266
269
|
message = self._get_message(record_data_or_message, stream_instance)
|
270
|
+
yield from self._emit_queued_messages()
|
267
271
|
yield message
|
268
272
|
if message.type == MessageType.RECORD:
|
269
273
|
record = message.record
|
@@ -298,6 +302,11 @@ class AbstractSource(Source, ABC):
|
|
298
302
|
"""
|
299
303
|
return logger.isEnabledFor(logging.DEBUG)
|
300
304
|
|
305
|
+
def _emit_queued_messages(self):
|
306
|
+
if self.message_repository:
|
307
|
+
yield from self.message_repository.consume_queue()
|
308
|
+
return
|
309
|
+
|
301
310
|
def _read_full_refresh(
|
302
311
|
self,
|
303
312
|
logger: logging.Logger,
|
@@ -357,3 +366,7 @@ class AbstractSource(Source, ABC):
|
|
357
366
|
return record_data_or_message
|
358
367
|
else:
|
359
368
|
return stream_data_to_airbyte_message(stream.name, record_data_or_message, stream.transformer, stream.get_json_schema())
|
369
|
+
|
370
|
+
@property
|
371
|
+
def message_repository(self) -> Union[None, MessageRepository]:
|
372
|
+
return None
|
@@ -580,10 +580,40 @@ definitions:
|
|
580
580
|
- "{{ config['record_cursor'] }}"
|
581
581
|
datetime_format:
|
582
582
|
title: Cursor Field Datetime Format
|
583
|
-
description:
|
583
|
+
description: |
|
584
|
+
The datetime format of the Cursor Field. Use placeholders starting with "%" to describe the format the API is using. The following placeholders are available:
|
585
|
+
* **%s**: Epoch unix timestamp - `1686218963`
|
586
|
+
* **%a**: Weekday (abbreviated) - `Sun`
|
587
|
+
* **%A**: Weekday (full) - `Sunday`
|
588
|
+
* **%w**: Weekday (decimal) - `0` (Sunday), `6` (Saturday)
|
589
|
+
* **%d**: Day of the month (zero-padded) - `01`, `02`, ..., `31`
|
590
|
+
* **%b**: Month (abbreviated) - `Jan`
|
591
|
+
* **%B**: Month (full) - `January`
|
592
|
+
* **%m**: Month (zero-padded) - `01`, `02`, ..., `12`
|
593
|
+
* **%y**: Year (without century, zero-padded) - `00`, `01`, ..., `99`
|
594
|
+
* **%Y**: Year (with century) - `0001`, `0002`, ..., `9999`
|
595
|
+
* **%H**: Hour (24-hour, zero-padded) - `00`, `01`, ..., `23`
|
596
|
+
* **%I**: Hour (12-hour, zero-padded) - `01`, `02`, ..., `12`
|
597
|
+
* **%p**: AM/PM indicator
|
598
|
+
* **%M**: Minute (zero-padded) - `00`, `01`, ..., `59`
|
599
|
+
* **%S**: Second (zero-padded) - `00`, `01`, ..., `59`
|
600
|
+
* **%f**: Microsecond (zero-padded to 6 digits) - `000000`
|
601
|
+
* **%z**: UTC offset - `(empty)`, `+0000`, `-0400`
|
602
|
+
* **%Z**: Time zone name - `(empty)`, `UTC`, `GMT`
|
603
|
+
* **%j**: Day of the year (zero-padded) - `001`, `002`, ..., `366`
|
604
|
+
* **%U**: Week number of the year (starting Sunday) - `00`, ..., `53`
|
605
|
+
* **%W**: Week number of the year (starting Monday) - `00`, ..., `53`
|
606
|
+
* **%c**: Date and time - `Tue Aug 16 21:30:00 1988`
|
607
|
+
* **%x**: Date standard format - `08/16/1988`
|
608
|
+
* **%X**: Time standard format - `21:30:00`
|
609
|
+
* **%%**: Literal '%' character
|
610
|
+
|
611
|
+
Some placeholders depend on the locale of the underlying system - in most cases this locale is configured as en/US. For more information see the [Python documentation](https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes).
|
584
612
|
type: string
|
585
613
|
examples:
|
586
614
|
- "%Y-%m-%dT%H:%M:%S.%f%z"
|
615
|
+
- "%Y-%m-%d"
|
616
|
+
- "%s"
|
587
617
|
cursor_granularity:
|
588
618
|
title: Cursor Granularity
|
589
619
|
description:
|
@@ -1283,11 +1313,39 @@ definitions:
|
|
1283
1313
|
- "{{ config['start_time'] }}"
|
1284
1314
|
datetime_format:
|
1285
1315
|
title: Datetime Format
|
1286
|
-
description:
|
1316
|
+
description: |
|
1317
|
+
Format of the datetime value. Defaults to "%Y-%m-%dT%H:%M:%S.%f%z" if left empty. Use placeholders starting with "%" to describe the format the API is using. The following placeholders are available:
|
1318
|
+
* **%s**: Epoch unix timestamp - `1686218963`
|
1319
|
+
* **%a**: Weekday (abbreviated) - `Sun`
|
1320
|
+
* **%A**: Weekday (full) - `Sunday`
|
1321
|
+
* **%w**: Weekday (decimal) - `0` (Sunday), `6` (Saturday)
|
1322
|
+
* **%d**: Day of the month (zero-padded) - `01`, `02`, ..., `31`
|
1323
|
+
* **%b**: Month (abbreviated) - `Jan`
|
1324
|
+
* **%B**: Month (full) - `January`
|
1325
|
+
* **%m**: Month (zero-padded) - `01`, `02`, ..., `12`
|
1326
|
+
* **%y**: Year (without century, zero-padded) - `00`, `01`, ..., `99`
|
1327
|
+
* **%Y**: Year (with century) - `0001`, `0002`, ..., `9999`
|
1328
|
+
* **%H**: Hour (24-hour, zero-padded) - `00`, `01`, ..., `23`
|
1329
|
+
* **%I**: Hour (12-hour, zero-padded) - `01`, `02`, ..., `12`
|
1330
|
+
* **%p**: AM/PM indicator
|
1331
|
+
* **%M**: Minute (zero-padded) - `00`, `01`, ..., `59`
|
1332
|
+
* **%S**: Second (zero-padded) - `00`, `01`, ..., `59`
|
1333
|
+
* **%f**: Microsecond (zero-padded to 6 digits) - `000000`, `000001`, ..., `999999`
|
1334
|
+
* **%z**: UTC offset - `(empty)`, `+0000`, `-0400`, `+1030`, `+063415`, `-030712.345216`
|
1335
|
+
* **%Z**: Time zone name - `(empty)`, `UTC`, `GMT`
|
1336
|
+
* **%j**: Day of the year (zero-padded) - `001`, `002`, ..., `366`
|
1337
|
+
* **%U**: Week number of the year (Sunday as first day) - `00`, `01`, ..., `53`
|
1338
|
+
* **%W**: Week number of the year (Monday as first day) - `00`, `01`, ..., `53`
|
1339
|
+
* **%c**: Date and time representation - `Tue Aug 16 21:30:00 1988`
|
1340
|
+
* **%x**: Date representation - `08/16/1988`
|
1341
|
+
* **%X**: Time representation - `21:30:00`
|
1342
|
+
* **%%**: Literal '%' character
|
1343
|
+
|
1344
|
+
Some placeholders depend on the locale of the underlying system - in most cases this locale is configured as en/US. For more information see the [Python documentation](https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes).
|
1287
1345
|
type: string
|
1288
1346
|
default: ""
|
1289
1347
|
examples:
|
1290
|
-
- "%Y-%m-%dT%H:%M:%S.%f%"
|
1348
|
+
- "%Y-%m-%dT%H:%M:%S.%f%z"
|
1291
1349
|
- "%Y-%m-%d"
|
1292
1350
|
- "%s"
|
1293
1351
|
max_datetime:
|
@@ -26,6 +26,7 @@ from airbyte_cdk.sources.declarative.parsers.manifest_component_transformer impo
|
|
26
26
|
from airbyte_cdk.sources.declarative.parsers.manifest_reference_resolver import ManifestReferenceResolver
|
27
27
|
from airbyte_cdk.sources.declarative.parsers.model_to_component_factory import ModelToComponentFactory
|
28
28
|
from airbyte_cdk.sources.declarative.types import ConnectionDefinition
|
29
|
+
from airbyte_cdk.sources.message import MessageRepository
|
29
30
|
from airbyte_cdk.sources.streams.core import Stream
|
30
31
|
from jsonschema.exceptions import ValidationError
|
31
32
|
from jsonschema.validators import validate
|
@@ -61,6 +62,7 @@ class ManifestDeclarativeSource(DeclarativeSource):
|
|
61
62
|
self._debug = debug
|
62
63
|
self._emit_connector_builder_messages = emit_connector_builder_messages
|
63
64
|
self._constructor = component_factory if component_factory else ModelToComponentFactory(emit_connector_builder_messages)
|
65
|
+
self._message_repository = self._constructor.get_message_repository()
|
64
66
|
|
65
67
|
self._validate_source()
|
66
68
|
|
@@ -68,6 +70,10 @@ class ManifestDeclarativeSource(DeclarativeSource):
|
|
68
70
|
def resolved_manifest(self) -> Mapping[str, Any]:
|
69
71
|
return self._source_config
|
70
72
|
|
73
|
+
@property
|
74
|
+
def message_repository(self) -> Union[None, MessageRepository]:
|
75
|
+
return self._message_repository
|
76
|
+
|
71
77
|
@property
|
72
78
|
def connection_checker(self) -> ConnectionChecker:
|
73
79
|
check = self._source_config["check"]
|
@@ -453,8 +453,8 @@ class MinMaxDatetime(BaseModel):
|
|
453
453
|
)
|
454
454
|
datetime_format: Optional[str] = Field(
|
455
455
|
"",
|
456
|
-
description='Format of the datetime value. Defaults to "%Y-%m-%dT%H:%M:%S.%f%z" if left empty. Use %
|
457
|
-
examples=["%Y-%m-%dT%H:%M:%S.%f%", "%Y-%m-%d", "%s"],
|
456
|
+
description='Format of the datetime value. Defaults to "%Y-%m-%dT%H:%M:%S.%f%z" if left empty. Use placeholders starting with "%" to describe the format the API is using. The following placeholders are available:\n * **%s**: Epoch unix timestamp - `1686218963`\n * **%a**: Weekday (abbreviated) - `Sun`\n * **%A**: Weekday (full) - `Sunday`\n * **%w**: Weekday (decimal) - `0` (Sunday), `6` (Saturday)\n * **%d**: Day of the month (zero-padded) - `01`, `02`, ..., `31`\n * **%b**: Month (abbreviated) - `Jan`\n * **%B**: Month (full) - `January`\n * **%m**: Month (zero-padded) - `01`, `02`, ..., `12`\n * **%y**: Year (without century, zero-padded) - `00`, `01`, ..., `99`\n * **%Y**: Year (with century) - `0001`, `0002`, ..., `9999`\n * **%H**: Hour (24-hour, zero-padded) - `00`, `01`, ..., `23`\n * **%I**: Hour (12-hour, zero-padded) - `01`, `02`, ..., `12`\n * **%p**: AM/PM indicator\n * **%M**: Minute (zero-padded) - `00`, `01`, ..., `59`\n * **%S**: Second (zero-padded) - `00`, `01`, ..., `59`\n * **%f**: Microsecond (zero-padded to 6 digits) - `000000`, `000001`, ..., `999999`\n * **%z**: UTC offset - `(empty)`, `+0000`, `-0400`, `+1030`, `+063415`, `-030712.345216`\n * **%Z**: Time zone name - `(empty)`, `UTC`, `GMT`\n * **%j**: Day of the year (zero-padded) - `001`, `002`, ..., `366`\n * **%U**: Week number of the year (Sunday as first day) - `00`, `01`, ..., `53`\n * **%W**: Week number of the year (Monday as first day) - `00`, `01`, ..., `53`\n * **%c**: Date and time representation - `Tue Aug 16 21:30:00 1988`\n * **%x**: Date representation - `08/16/1988`\n * **%X**: Time representation - `21:30:00`\n * **%%**: Literal \'%\' character\n\n Some placeholders depend on the locale of the underlying system - in most cases this locale is configured as en/US. For more information see the [Python documentation](https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes).\n',
|
457
|
+
examples=["%Y-%m-%dT%H:%M:%S.%f%z", "%Y-%m-%d", "%s"],
|
458
458
|
title="Datetime Format",
|
459
459
|
)
|
460
460
|
max_datetime: Optional[str] = Field(
|
@@ -806,8 +806,8 @@ class DatetimeBasedCursor(BaseModel):
|
|
806
806
|
)
|
807
807
|
datetime_format: str = Field(
|
808
808
|
...,
|
809
|
-
description="The datetime format of the Cursor Field.",
|
810
|
-
examples=["%Y-%m-%dT%H:%M:%S.%f%z"],
|
809
|
+
description="The datetime format of the Cursor Field. Use placeholders starting with \"%\" to describe the format the API is using. The following placeholders are available:\n * **%s**: Epoch unix timestamp - `1686218963`\n * **%a**: Weekday (abbreviated) - `Sun`\n * **%A**: Weekday (full) - `Sunday`\n * **%w**: Weekday (decimal) - `0` (Sunday), `6` (Saturday)\n * **%d**: Day of the month (zero-padded) - `01`, `02`, ..., `31`\n * **%b**: Month (abbreviated) - `Jan`\n * **%B**: Month (full) - `January`\n * **%m**: Month (zero-padded) - `01`, `02`, ..., `12`\n * **%y**: Year (without century, zero-padded) - `00`, `01`, ..., `99`\n * **%Y**: Year (with century) - `0001`, `0002`, ..., `9999`\n * **%H**: Hour (24-hour, zero-padded) - `00`, `01`, ..., `23`\n * **%I**: Hour (12-hour, zero-padded) - `01`, `02`, ..., `12`\n * **%p**: AM/PM indicator\n * **%M**: Minute (zero-padded) - `00`, `01`, ..., `59`\n * **%S**: Second (zero-padded) - `00`, `01`, ..., `59`\n * **%f**: Microsecond (zero-padded to 6 digits) - `000000`\n * **%z**: UTC offset - `(empty)`, `+0000`, `-0400`\n * **%Z**: Time zone name - `(empty)`, `UTC`, `GMT`\n * **%j**: Day of the year (zero-padded) - `001`, `002`, ..., `366`\n * **%U**: Week number of the year (starting Sunday) - `00`, ..., `53`\n * **%W**: Week number of the year (starting Monday) - `00`, ..., `53`\n * **%c**: Date and time - `Tue Aug 16 21:30:00 1988`\n * **%x**: Date standard format - `08/16/1988`\n * **%X**: Time standard format - `21:30:00`\n * **%%**: Literal '%' character\n\n Some placeholders depend on the locale of the underlying system - in most cases this locale is configured as en/US. For more information see the [Python documentation](https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes).\n",
|
810
|
+
examples=["%Y-%m-%dT%H:%M:%S.%f%z", "%Y-%m-%d", "%s"],
|
811
811
|
title="Cursor Field Datetime Format",
|
812
812
|
)
|
813
813
|
cursor_granularity: Optional[str] = Field(
|
@@ -100,6 +100,7 @@ from airbyte_cdk.sources.declarative.stream_slicers import CartesianProductStrea
|
|
100
100
|
from airbyte_cdk.sources.declarative.transformations import AddFields, RemoveFields
|
101
101
|
from airbyte_cdk.sources.declarative.transformations.add_fields import AddedFieldDefinition
|
102
102
|
from airbyte_cdk.sources.declarative.types import Config
|
103
|
+
from airbyte_cdk.sources.message import InMemoryMessageRepository
|
103
104
|
from pydantic import BaseModel
|
104
105
|
|
105
106
|
ComponentDefinition: Union[Literal, Mapping, List]
|
@@ -121,6 +122,7 @@ class ModelToComponentFactory:
|
|
121
122
|
self._limit_slices_fetched = limit_slices_fetched
|
122
123
|
self._emit_connector_builder_messages = emit_connector_builder_messages
|
123
124
|
self._disable_retries = disable_retries
|
125
|
+
self._message_repository = InMemoryMessageRepository()
|
124
126
|
|
125
127
|
def _init_mappings(self):
|
126
128
|
self.PYDANTIC_MODEL_TO_CONSTRUCTOR: [Type[BaseModel], Callable] = {
|
@@ -675,8 +677,7 @@ class ModelToComponentFactory:
|
|
675
677
|
def create_no_pagination(model: NoPaginationModel, config: Config, **kwargs) -> NoPagination:
|
676
678
|
return NoPagination(parameters={})
|
677
679
|
|
678
|
-
|
679
|
-
def create_oauth_authenticator(model: OAuthAuthenticatorModel, config: Config, **kwargs) -> DeclarativeOauth2Authenticator:
|
680
|
+
def create_oauth_authenticator(self, model: OAuthAuthenticatorModel, config: Config, **kwargs) -> DeclarativeOauth2Authenticator:
|
680
681
|
if model.refresh_token_updater:
|
681
682
|
return DeclarativeSingleUseRefreshTokenOauth2Authenticator(
|
682
683
|
config,
|
@@ -693,6 +694,7 @@ class ModelToComponentFactory:
|
|
693
694
|
refresh_request_body=InterpolatedMapping(model.refresh_request_body or {}, parameters=model.parameters).eval(config),
|
694
695
|
scopes=model.scopes,
|
695
696
|
token_expiry_date_format=model.token_expiry_date_format,
|
697
|
+
message_repository=self._message_repository,
|
696
698
|
)
|
697
699
|
return DeclarativeOauth2Authenticator(
|
698
700
|
access_token_name=model.access_token_name,
|
@@ -845,3 +847,6 @@ class ModelToComponentFactory:
|
|
845
847
|
return WaitUntilTimeFromHeaderBackoffStrategy(
|
846
848
|
header=model.header, parameters=model.parameters, config=config, min_wait=model.min_wait, regex=model.regex
|
847
849
|
)
|
850
|
+
|
851
|
+
def get_message_repository(self):
|
852
|
+
return self._message_repository
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2023 Airbyte, Inc., all rights reserved.
|
3
|
+
#
|
4
|
+
|
5
|
+
from abc import ABC, abstractmethod
|
6
|
+
from typing import Iterable
|
7
|
+
|
8
|
+
from airbyte_cdk.models import AirbyteMessage, Type
|
9
|
+
|
10
|
+
|
11
|
+
class MessageRepository(ABC):
|
12
|
+
@abstractmethod
|
13
|
+
def emit_message(self, message: AirbyteMessage) -> None:
|
14
|
+
raise NotImplementedError()
|
15
|
+
|
16
|
+
@abstractmethod
|
17
|
+
def consume_queue(self) -> Iterable[AirbyteMessage]:
|
18
|
+
raise NotImplementedError()
|
19
|
+
|
20
|
+
|
21
|
+
class InMemoryMessageRepository(MessageRepository):
|
22
|
+
def __init__(self):
|
23
|
+
self._message_queue = []
|
24
|
+
|
25
|
+
def emit_message(self, message: AirbyteMessage) -> None:
|
26
|
+
"""
|
27
|
+
:param message: As of today, only AirbyteControlMessages are supported given that supporting other types of message will need more
|
28
|
+
work and therefore this work has been postponed
|
29
|
+
"""
|
30
|
+
if message.type != Type.CONTROL:
|
31
|
+
raise ValueError("As of today, only AirbyteControlMessages are supported as part of the InMemoryMessageRepository")
|
32
|
+
self._message_queue.append(message)
|
33
|
+
|
34
|
+
def consume_queue(self) -> Iterable[AirbyteMessage]:
|
35
|
+
while self._message_queue:
|
36
|
+
yield self._message_queue.pop(0)
|
@@ -79,7 +79,12 @@ class AbstractOauth2Authenticator(AuthBase):
|
|
79
79
|
)
|
80
80
|
def _get_refresh_access_token_response(self):
|
81
81
|
try:
|
82
|
-
response = requests.request(
|
82
|
+
response = requests.request(
|
83
|
+
method="POST",
|
84
|
+
url=self.get_token_refresh_endpoint(),
|
85
|
+
data=self.build_refresh_request_body(),
|
86
|
+
headers={"Content-Type": "application/json"},
|
87
|
+
)
|
83
88
|
response.raise_for_status()
|
84
89
|
return response.json()
|
85
90
|
except requests.exceptions.RequestException as e:
|
@@ -6,7 +6,8 @@ from typing import Any, List, Mapping, Optional, Sequence, Tuple, Union
|
|
6
6
|
|
7
7
|
import dpath
|
8
8
|
import pendulum
|
9
|
-
from airbyte_cdk.config_observation import emit_configuration_as_airbyte_control_message
|
9
|
+
from airbyte_cdk.config_observation import create_connector_config_control_message, emit_configuration_as_airbyte_control_message
|
10
|
+
from airbyte_cdk.sources.message import MessageRepository
|
10
11
|
from airbyte_cdk.sources.streams.http.requests_native_auth.abstract_oauth import AbstractOauth2Authenticator
|
11
12
|
|
12
13
|
|
@@ -115,6 +116,7 @@ class SingleUseRefreshTokenOauth2Authenticator(Oauth2Authenticator):
|
|
115
116
|
refresh_token_config_path: Sequence[str] = ("credentials", "refresh_token"),
|
116
117
|
token_expiry_date_config_path: Sequence[str] = ("credentials", "token_expiry_date"),
|
117
118
|
token_expiry_date_format: Optional[str] = None,
|
119
|
+
message_repository: MessageRepository = None,
|
118
120
|
):
|
119
121
|
"""
|
120
122
|
|
@@ -144,6 +146,7 @@ class SingleUseRefreshTokenOauth2Authenticator(Oauth2Authenticator):
|
|
144
146
|
self._token_expiry_date_format = token_expiry_date_format
|
145
147
|
self._refresh_token_name = refresh_token_name
|
146
148
|
self._connector_config = connector_config
|
149
|
+
self._message_repository = message_repository
|
147
150
|
super().__init__(
|
148
151
|
token_refresh_endpoint,
|
149
152
|
self.get_client_id(),
|
@@ -211,7 +214,11 @@ class SingleUseRefreshTokenOauth2Authenticator(Oauth2Authenticator):
|
|
211
214
|
self.access_token = new_access_token
|
212
215
|
self.set_refresh_token(new_refresh_token)
|
213
216
|
self.set_token_expiry_date(new_token_expiry_date)
|
214
|
-
|
217
|
+
if self._message_repository:
|
218
|
+
self._message_repository.emit_message(create_connector_config_control_message(self._connector_config))
|
219
|
+
else:
|
220
|
+
# FIXME emit_configuration_as_airbyte_control_message as been deprecated in favor of package airbyte_cdk.sources.message
|
221
|
+
emit_configuration_as_airbyte_control_message(self._connector_config)
|
215
222
|
return self.access_token
|
216
223
|
|
217
224
|
def refresh_access_token(self) -> Tuple[str, str, str]:
|
@@ -0,0 +1,80 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2023 Airbyte, Inc., all rights reserved.
|
3
|
+
#
|
4
|
+
|
5
|
+
from typing import Any, Dict, Union
|
6
|
+
|
7
|
+
from airbyte_cdk.models import AirbyteRecordMessage
|
8
|
+
from airbyte_cdk.sources.declarative.datetime.datetime_parser import DatetimeParser
|
9
|
+
|
10
|
+
|
11
|
+
class DatetimeFormatInferrer:
|
12
|
+
"""
|
13
|
+
This class is used to detect toplevel fields in records that might be datetime values, along with the used format.
|
14
|
+
"""
|
15
|
+
|
16
|
+
def __init__(self):
|
17
|
+
self._parser = DatetimeParser()
|
18
|
+
self._datetime_candidates: Union[None, Dict[str, str]] = None
|
19
|
+
self._formats = [
|
20
|
+
"%Y-%m-%d",
|
21
|
+
"%Y-%m-%d %H:%M:%S",
|
22
|
+
"%Y-%m-%d %H:%M:%S.%f+00:00",
|
23
|
+
"%Y-%m-%dT%H:%M:%S.%f%z",
|
24
|
+
"%s",
|
25
|
+
"%d/%m/%Y %H:%M",
|
26
|
+
"%Y-%m",
|
27
|
+
"%d-%m-%Y",
|
28
|
+
"%Y-%m-%dT%H:%M:%SZ",
|
29
|
+
]
|
30
|
+
self._timestamp_heuristic_range = range(1_000_000_000, 2_000_000_000)
|
31
|
+
|
32
|
+
def _can_be_datetime(self, value: Any) -> bool:
|
33
|
+
"""Checks if the value can be a datetime. This is the case if the value is a string or an integer between 1_000_000_000 and 2_000_000_000. This is separate from the format check for performance reasons"""
|
34
|
+
if isinstance(value, str) and (not value.isdecimal() or int(value) in self._timestamp_heuristic_range):
|
35
|
+
return True
|
36
|
+
if isinstance(value, int) and value in self._timestamp_heuristic_range:
|
37
|
+
return True
|
38
|
+
return False
|
39
|
+
|
40
|
+
def _matches_format(self, value: Any, format: str) -> bool:
|
41
|
+
"""Checks if the value matches the format"""
|
42
|
+
try:
|
43
|
+
self._parser.parse(value, format)
|
44
|
+
return True
|
45
|
+
except ValueError:
|
46
|
+
return False
|
47
|
+
|
48
|
+
def _initialize(self, record: AirbyteRecordMessage):
|
49
|
+
"""Initializes the internal state of the class"""
|
50
|
+
self._datetime_candidates = {}
|
51
|
+
for field_name, field_value in record.data.items():
|
52
|
+
if not self._can_be_datetime(field_value):
|
53
|
+
continue
|
54
|
+
for format in self._formats:
|
55
|
+
if self._matches_format(field_value, format):
|
56
|
+
self._datetime_candidates[field_name] = format
|
57
|
+
break
|
58
|
+
|
59
|
+
def _validate(self, record: AirbyteRecordMessage):
|
60
|
+
"""Validates that the record is consistent with the inferred datetime formats"""
|
61
|
+
for candidate_field_name in list(self._datetime_candidates.keys()):
|
62
|
+
candidate_field_format = self._datetime_candidates[candidate_field_name]
|
63
|
+
current_value = record.data.get(candidate_field_name, None)
|
64
|
+
if (
|
65
|
+
current_value is None
|
66
|
+
or not self._can_be_datetime(current_value)
|
67
|
+
or not self._matches_format(current_value, candidate_field_format)
|
68
|
+
):
|
69
|
+
self._datetime_candidates.pop(candidate_field_name)
|
70
|
+
|
71
|
+
def accumulate(self, record: AirbyteRecordMessage):
|
72
|
+
"""Analyzes the record and updates the internal state of candidate datetime fields"""
|
73
|
+
self._initialize(record) if self._datetime_candidates is None else self._validate(record)
|
74
|
+
|
75
|
+
def get_inferred_datetime_formats(self) -> Dict[str, str]:
|
76
|
+
"""
|
77
|
+
Returns the list of candidate datetime fields - the keys are the field names and the values are the inferred datetime formats.
|
78
|
+
For these fields the format was consistent across all visited records.
|
79
|
+
"""
|
80
|
+
return self._datetime_candidates or {}
|
@@ -134,6 +134,8 @@ airbyte_cdk/sources/declarative/transformations/transformation.py
|
|
134
134
|
airbyte_cdk/sources/deprecated/__init__.py
|
135
135
|
airbyte_cdk/sources/deprecated/base_source.py
|
136
136
|
airbyte_cdk/sources/deprecated/client.py
|
137
|
+
airbyte_cdk/sources/message/__init__.py
|
138
|
+
airbyte_cdk/sources/message/repository.py
|
137
139
|
airbyte_cdk/sources/singer/__init__.py
|
138
140
|
airbyte_cdk/sources/singer/singer_helpers.py
|
139
141
|
airbyte_cdk/sources/singer/source.py
|
@@ -165,6 +167,7 @@ airbyte_cdk/sources/utils/schema_models.py
|
|
165
167
|
airbyte_cdk/sources/utils/transform.py
|
166
168
|
airbyte_cdk/utils/__init__.py
|
167
169
|
airbyte_cdk/utils/airbyte_secrets_utils.py
|
170
|
+
airbyte_cdk/utils/datetime_format_inferrer.py
|
168
171
|
airbyte_cdk/utils/event_timing.py
|
169
172
|
airbyte_cdk/utils/schema_inferrer.py
|
170
173
|
airbyte_cdk/utils/stream_status_utils.py
|
@@ -256,6 +259,8 @@ unit_tests/sources/declarative/schema/source_test/__init__.py
|
|
256
259
|
unit_tests/sources/declarative/states/__init__.py
|
257
260
|
unit_tests/sources/declarative/stream_slicers/__init__.py
|
258
261
|
unit_tests/sources/declarative/stream_slicers/test_cartesian_product_stream_slicer.py
|
262
|
+
unit_tests/sources/message/__init__.py
|
263
|
+
unit_tests/sources/message/test_repository.py
|
259
264
|
unit_tests/sources/streams/__init__.py
|
260
265
|
unit_tests/sources/streams/test_availability_strategy.py
|
261
266
|
unit_tests/sources/streams/test_streams_core.py
|
@@ -267,6 +272,7 @@ unit_tests/sources/streams/http/auth/test_auth.py
|
|
267
272
|
unit_tests/sources/streams/http/requests_native_auth/__init__.py
|
268
273
|
unit_tests/sources/streams/http/requests_native_auth/test_requests_native_auth.py
|
269
274
|
unit_tests/utils/__init__.py
|
275
|
+
unit_tests/utils/test_datetime_format_inferrer.py
|
270
276
|
unit_tests/utils/test_schema_inferrer.py
|
271
277
|
unit_tests/utils/test_secret_utils.py
|
272
278
|
unit_tests/utils/test_stream_status_utils.py
|
@@ -17,7 +17,7 @@ setup(
|
|
17
17
|
name="airbyte-cdk",
|
18
18
|
# The version of the airbyte-cdk package is used at runtime to validate manifests. That validation must be
|
19
19
|
# updated if our semver format changes such as using release candidate versions.
|
20
|
-
version="0.40.
|
20
|
+
version="0.40.4",
|
21
21
|
description="A framework for writing Airbyte Connectors.",
|
22
22
|
long_description=README,
|
23
23
|
long_description_content_type="text/markdown",
|