airbyte-cdk 0.40.2__tar.gz → 0.40.3__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (277) hide show
  1. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/PKG-INFO +1 -1
  2. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/connector_builder/message_grouper.py +6 -1
  3. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/connector_builder/models.py +1 -0
  4. airbyte-cdk-0.40.3/airbyte_cdk/utils/datetime_format_inferrer.py +80 -0
  5. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk.egg-info/PKG-INFO +1 -1
  6. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk.egg-info/SOURCES.txt +2 -0
  7. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/setup.py +1 -1
  8. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/connector_builder/test_connector_builder_handler.py +3 -0
  9. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/connector_builder/test_message_grouper.py +8 -6
  10. airbyte-cdk-0.40.3/unit_tests/utils/test_datetime_format_inferrer.py +53 -0
  11. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/LICENSE.txt +0 -0
  12. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/README.md +0 -0
  13. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/__init__.py +0 -0
  14. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/config_observation.py +0 -0
  15. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/connector.py +0 -0
  16. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/connector_builder/__init__.py +0 -0
  17. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/connector_builder/connector_builder_handler.py +0 -0
  18. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/connector_builder/main.py +0 -0
  19. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/destinations/__init__.py +0 -0
  20. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/destinations/destination.py +0 -0
  21. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/entrypoint.py +0 -0
  22. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/exception_handler.py +0 -0
  23. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/logger.py +0 -0
  24. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/models/__init__.py +0 -0
  25. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/models/airbyte_protocol.py +0 -0
  26. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/models/well_known_types.py +0 -0
  27. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/py.typed +0 -0
  28. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/__init__.py +0 -0
  29. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/abstract_source.py +0 -0
  30. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/config.py +0 -0
  31. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/connector_state_manager.py +0 -0
  32. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/__init__.py +0 -0
  33. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/auth/__init__.py +0 -0
  34. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/auth/declarative_authenticator.py +0 -0
  35. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/auth/oauth.py +0 -0
  36. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/auth/token.py +0 -0
  37. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/checks/__init__.py +0 -0
  38. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/checks/check_stream.py +0 -0
  39. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/checks/connection_checker.py +0 -0
  40. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/create_partial.py +0 -0
  41. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/datetime/__init__.py +0 -0
  42. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/datetime/datetime_parser.py +0 -0
  43. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/datetime/min_max_datetime.py +0 -0
  44. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/declarative_component_schema.yaml +0 -0
  45. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/declarative_source.py +0 -0
  46. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/declarative_stream.py +0 -0
  47. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/decoders/__init__.py +0 -0
  48. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/decoders/decoder.py +0 -0
  49. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/decoders/json_decoder.py +0 -0
  50. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/exceptions.py +0 -0
  51. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/extractors/__init__.py +0 -0
  52. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/extractors/dpath_extractor.py +0 -0
  53. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/extractors/http_selector.py +0 -0
  54. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/extractors/record_extractor.py +0 -0
  55. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/extractors/record_filter.py +0 -0
  56. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/extractors/record_selector.py +0 -0
  57. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/incremental/__init__.py +0 -0
  58. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/incremental/datetime_based_cursor.py +0 -0
  59. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/interpolation/__init__.py +0 -0
  60. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/interpolation/filters.py +0 -0
  61. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/interpolation/interpolated_boolean.py +0 -0
  62. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/interpolation/interpolated_mapping.py +0 -0
  63. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/interpolation/interpolated_nested_mapping.py +0 -0
  64. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/interpolation/interpolated_string.py +0 -0
  65. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/interpolation/interpolation.py +0 -0
  66. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/interpolation/jinja.py +0 -0
  67. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/interpolation/macros.py +0 -0
  68. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/manifest_declarative_source.py +0 -0
  69. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/models/__init__.py +0 -0
  70. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/models/declarative_component_schema.py +0 -0
  71. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/parsers/__init__.py +0 -0
  72. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/parsers/class_types_registry.py +0 -0
  73. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/parsers/custom_exceptions.py +0 -0
  74. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/parsers/default_implementation_registry.py +0 -0
  75. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/parsers/manifest_component_transformer.py +0 -0
  76. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/parsers/manifest_reference_resolver.py +0 -0
  77. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py +0 -0
  78. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/partition_routers/__init__.py +0 -0
  79. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/partition_routers/list_partition_router.py +0 -0
  80. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/partition_routers/single_partition_router.py +0 -0
  81. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/partition_routers/substream_partition_router.py +0 -0
  82. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/requesters/__init__.py +0 -0
  83. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/requesters/error_handlers/__init__.py +0 -0
  84. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/requesters/error_handlers/backoff_strategies/__init__.py +0 -0
  85. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/requesters/error_handlers/backoff_strategies/constant_backoff_strategy.py +0 -0
  86. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/requesters/error_handlers/backoff_strategies/exponential_backoff_strategy.py +0 -0
  87. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/requesters/error_handlers/backoff_strategies/header_helper.py +0 -0
  88. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/requesters/error_handlers/backoff_strategies/wait_time_from_header_backoff_strategy.py +0 -0
  89. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/requesters/error_handlers/backoff_strategies/wait_until_time_from_header_backoff_strategy.py +0 -0
  90. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/requesters/error_handlers/backoff_strategy.py +0 -0
  91. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/requesters/error_handlers/composite_error_handler.py +0 -0
  92. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/requesters/error_handlers/default_error_handler.py +0 -0
  93. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/requesters/error_handlers/error_handler.py +0 -0
  94. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/requesters/error_handlers/http_response_filter.py +0 -0
  95. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/requesters/error_handlers/response_action.py +0 -0
  96. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/requesters/error_handlers/response_status.py +0 -0
  97. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/requesters/http_requester.py +0 -0
  98. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/requesters/paginators/__init__.py +0 -0
  99. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/requesters/paginators/default_paginator.py +0 -0
  100. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/requesters/paginators/no_pagination.py +0 -0
  101. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/requesters/paginators/paginator.py +0 -0
  102. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/requesters/paginators/strategies/__init__.py +0 -0
  103. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/requesters/paginators/strategies/cursor_pagination_strategy.py +0 -0
  104. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/requesters/paginators/strategies/offset_increment.py +0 -0
  105. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/requesters/paginators/strategies/page_increment.py +0 -0
  106. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/requesters/paginators/strategies/pagination_strategy.py +0 -0
  107. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/requesters/request_option.py +0 -0
  108. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/requesters/request_options/__init__.py +0 -0
  109. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/requesters/request_options/interpolated_nested_request_input_provider.py +0 -0
  110. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/requesters/request_options/interpolated_request_input_provider.py +0 -0
  111. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/requesters/request_options/interpolated_request_options_provider.py +0 -0
  112. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/requesters/request_options/request_options_provider.py +0 -0
  113. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/requesters/request_path.py +0 -0
  114. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/requesters/requester.py +0 -0
  115. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/retrievers/__init__.py +0 -0
  116. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/retrievers/retriever.py +0 -0
  117. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/retrievers/simple_retriever.py +0 -0
  118. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/schema/__init__.py +0 -0
  119. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/schema/default_schema_loader.py +0 -0
  120. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/schema/inline_schema_loader.py +0 -0
  121. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/schema/json_file_schema_loader.py +0 -0
  122. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/schema/schema_loader.py +0 -0
  123. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/spec/__init__.py +0 -0
  124. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/spec/spec.py +0 -0
  125. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/stream_slicers/__init__.py +0 -0
  126. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/stream_slicers/cartesian_product_stream_slicer.py +0 -0
  127. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/stream_slicers/stream_slicer.py +0 -0
  128. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/transformations/__init__.py +0 -0
  129. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/transformations/add_fields.py +0 -0
  130. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/transformations/remove_fields.py +0 -0
  131. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/transformations/transformation.py +0 -0
  132. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/types.py +0 -0
  133. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/declarative/yaml_declarative_source.py +0 -0
  134. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/deprecated/__init__.py +0 -0
  135. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/deprecated/base_source.py +0 -0
  136. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/deprecated/client.py +0 -0
  137. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/singer/__init__.py +0 -0
  138. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/singer/singer_helpers.py +0 -0
  139. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/singer/source.py +0 -0
  140. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/source.py +0 -0
  141. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/streams/__init__.py +0 -0
  142. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/streams/availability_strategy.py +0 -0
  143. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/streams/core.py +0 -0
  144. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/streams/http/__init__.py +0 -0
  145. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/streams/http/auth/__init__.py +0 -0
  146. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/streams/http/auth/core.py +0 -0
  147. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/streams/http/auth/oauth.py +0 -0
  148. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/streams/http/auth/token.py +0 -0
  149. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/streams/http/availability_strategy.py +0 -0
  150. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/streams/http/exceptions.py +0 -0
  151. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/streams/http/http.py +0 -0
  152. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/streams/http/rate_limiting.py +0 -0
  153. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/streams/http/requests_native_auth/__init__.py +0 -0
  154. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/streams/http/requests_native_auth/abstract_oauth.py +0 -0
  155. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/streams/http/requests_native_auth/abstract_token.py +0 -0
  156. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/streams/http/requests_native_auth/oauth.py +0 -0
  157. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/streams/http/requests_native_auth/token.py +0 -0
  158. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/streams/utils/__init__.py +0 -0
  159. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/streams/utils/stream_helper.py +0 -0
  160. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/utils/__init__.py +0 -0
  161. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/utils/casing.py +0 -0
  162. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/utils/catalog_helpers.py +0 -0
  163. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/utils/record_helper.py +0 -0
  164. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/utils/schema_helpers.py +0 -0
  165. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/utils/schema_models.py +0 -0
  166. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/sources/utils/transform.py +0 -0
  167. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/utils/__init__.py +0 -0
  168. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/utils/airbyte_secrets_utils.py +0 -0
  169. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/utils/event_timing.py +0 -0
  170. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/utils/schema_inferrer.py +0 -0
  171. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/utils/stream_status_utils.py +0 -0
  172. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk/utils/traced_exception.py +0 -0
  173. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk.egg-info/dependency_links.txt +0 -0
  174. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk.egg-info/requires.txt +0 -0
  175. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/airbyte_cdk.egg-info/top_level.txt +0 -0
  176. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/pyproject.toml +0 -0
  177. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/setup.cfg +0 -0
  178. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/source_declarative_manifest/__init__.py +0 -0
  179. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/source_declarative_manifest/main.py +0 -0
  180. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/connector_builder/__init__.py +0 -0
  181. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/connector_builder/utils.py +0 -0
  182. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/destinations/__init__.py +0 -0
  183. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/destinations/test_destination.py +0 -0
  184. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/singer/__init__.py +0 -0
  185. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/singer/test_singer_helpers.py +0 -0
  186. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/singer/test_singer_source.py +0 -0
  187. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/__init__.py +0 -0
  188. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/__init__.py +0 -0
  189. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/auth/__init__.py +0 -0
  190. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/auth/test_oauth.py +0 -0
  191. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/auth/test_session_token_auth.py +0 -0
  192. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/auth/test_token_auth.py +0 -0
  193. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/checks/__init__.py +0 -0
  194. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/checks/test_check_stream.py +0 -0
  195. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/decoders/__init__.py +0 -0
  196. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/decoders/test_json_decoder.py +0 -0
  197. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/external_component.py +0 -0
  198. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/extractors/__init__.py +0 -0
  199. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/extractors/test_dpath_extractor.py +0 -0
  200. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/extractors/test_record_filter.py +0 -0
  201. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/extractors/test_record_selector.py +0 -0
  202. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/incremental/__init__.py +0 -0
  203. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/incremental/test_datetime_based_cursor.py +0 -0
  204. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/interpolation/__init__.py +0 -0
  205. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/interpolation/test_filters.py +0 -0
  206. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/interpolation/test_interpolated_boolean.py +0 -0
  207. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/interpolation/test_interpolated_mapping.py +0 -0
  208. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/interpolation/test_interpolated_nested_mapping.py +0 -0
  209. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/interpolation/test_interpolated_string.py +0 -0
  210. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/interpolation/test_jinja.py +0 -0
  211. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/interpolation/test_macros.py +0 -0
  212. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/parsers/__init__.py +0 -0
  213. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/parsers/test_manifest_component_transformer.py +0 -0
  214. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/parsers/test_manifest_reference_resolver.py +0 -0
  215. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/parsers/test_model_to_component_factory.py +0 -0
  216. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/parsers/testing_components.py +0 -0
  217. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/partition_routers/__init__.py +0 -0
  218. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/partition_routers/test_list_partition_router.py +0 -0
  219. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/partition_routers/test_single_partition_router.py +0 -0
  220. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/partition_routers/test_substream_partition_router.py +0 -0
  221. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/requesters/__init__.py +0 -0
  222. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/requesters/error_handlers/__init__.py +0 -0
  223. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/requesters/error_handlers/backoff_strategies/__init__.py +0 -0
  224. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/requesters/error_handlers/backoff_strategies/test_constant_backoff.py +0 -0
  225. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/requesters/error_handlers/backoff_strategies/test_exponential_backoff.py +0 -0
  226. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/requesters/error_handlers/backoff_strategies/test_header_helper.py +0 -0
  227. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/requesters/error_handlers/backoff_strategies/test_wait_time_from_header.py +0 -0
  228. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/requesters/error_handlers/backoff_strategies/test_wait_until_time_from_header.py +0 -0
  229. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/requesters/error_handlers/test_composite_error_handler.py +0 -0
  230. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/requesters/error_handlers/test_default_error_handler.py +0 -0
  231. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/requesters/error_handlers/test_http_response_filter.py +0 -0
  232. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/requesters/error_handlers/test_response_status.py +0 -0
  233. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/requesters/paginators/__init__.py +0 -0
  234. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/requesters/paginators/test_cursor_pagination_strategy.py +0 -0
  235. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/requesters/paginators/test_default_paginator.py +0 -0
  236. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/requesters/paginators/test_no_paginator.py +0 -0
  237. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/requesters/paginators/test_offset_increment.py +0 -0
  238. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/requesters/paginators/test_page_increment.py +0 -0
  239. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/requesters/paginators/test_request_option.py +0 -0
  240. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/requesters/request_options/__init__.py +0 -0
  241. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/requesters/request_options/test_interpolated_request_options_provider.py +0 -0
  242. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/requesters/test_http_requester.py +0 -0
  243. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/requesters/test_interpolated_request_input_provider.py +0 -0
  244. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/retrievers/__init__.py +0 -0
  245. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/retrievers/test_simple_retriever.py +0 -0
  246. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/schema/__init__.py +0 -0
  247. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/schema/source_test/SourceTest.py +0 -0
  248. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/schema/source_test/__init__.py +0 -0
  249. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/schema/test_default_schema_loader.py +0 -0
  250. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/schema/test_inline_schema_loader.py +0 -0
  251. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/schema/test_json_file_schema_loader.py +0 -0
  252. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/states/__init__.py +0 -0
  253. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/stream_slicers/__init__.py +0 -0
  254. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/stream_slicers/test_cartesian_product_stream_slicer.py +0 -0
  255. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/test_create_partial.py +0 -0
  256. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/test_declarative_stream.py +0 -0
  257. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/test_manifest_declarative_source.py +0 -0
  258. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/declarative/test_yaml_declarative_source.py +0 -0
  259. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/streams/__init__.py +0 -0
  260. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/streams/http/__init__.py +0 -0
  261. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/streams/http/auth/__init__.py +0 -0
  262. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/streams/http/auth/test_auth.py +0 -0
  263. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/streams/http/requests_native_auth/__init__.py +0 -0
  264. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/streams/http/requests_native_auth/test_requests_native_auth.py +0 -0
  265. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/streams/http/test_availability_strategy.py +0 -0
  266. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/streams/http/test_http.py +0 -0
  267. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/streams/test_availability_strategy.py +0 -0
  268. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/streams/test_streams_core.py +0 -0
  269. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/test_abstract_source.py +0 -0
  270. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/test_config.py +0 -0
  271. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/test_connector_state_manager.py +0 -0
  272. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/sources/test_source.py +0 -0
  273. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/utils/__init__.py +0 -0
  274. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/utils/test_schema_inferrer.py +0 -0
  275. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/utils/test_secret_utils.py +0 -0
  276. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/utils/test_stream_status_utils.py +0 -0
  277. {airbyte-cdk-0.40.2 → airbyte-cdk-0.40.3}/unit_tests/utils/test_traced_exception.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: airbyte-cdk
3
- Version: 0.40.2
3
+ Version: 0.40.3
4
4
  Summary: A framework for writing Airbyte Connectors.
5
5
  Home-page: https://github.com/airbytehq/airbyte
6
6
  Author: Airbyte
@@ -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):
@@ -80,10 +83,11 @@ class MessageGrouper:
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
85
  latest_config_update=latest_config_update.connectorConfig.config if latest_config_update else self._clean_config(config),
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:
@@ -48,6 +48,7 @@ class StreamRead(object):
48
48
  slices: List[StreamReadSlices]
49
49
  test_read_limit_reached: bool
50
50
  inferred_schema: Optional[Dict[str, Any]]
51
+ inferred_datetime_formats: Optional[Dict[str, str]]
51
52
  latest_config_update: Optional[Dict[str, Any]]
52
53
 
53
54
 
@@ -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 {}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: airbyte-cdk
3
- Version: 0.40.2
3
+ Version: 0.40.3
4
4
  Summary: A framework for writing Airbyte Connectors.
5
5
  Home-page: https://github.com/airbytehq/airbyte
6
6
  Author: Airbyte
@@ -165,6 +165,7 @@ airbyte_cdk/sources/utils/schema_models.py
165
165
  airbyte_cdk/sources/utils/transform.py
166
166
  airbyte_cdk/utils/__init__.py
167
167
  airbyte_cdk/utils/airbyte_secrets_utils.py
168
+ airbyte_cdk/utils/datetime_format_inferrer.py
168
169
  airbyte_cdk/utils/event_timing.py
169
170
  airbyte_cdk/utils/schema_inferrer.py
170
171
  airbyte_cdk/utils/stream_status_utils.py
@@ -267,6 +268,7 @@ unit_tests/sources/streams/http/auth/test_auth.py
267
268
  unit_tests/sources/streams/http/requests_native_auth/__init__.py
268
269
  unit_tests/sources/streams/http/requests_native_auth/test_requests_native_auth.py
269
270
  unit_tests/utils/__init__.py
271
+ unit_tests/utils/test_datetime_format_inferrer.py
270
272
  unit_tests/utils/test_schema_inferrer.py
271
273
  unit_tests/utils/test_secret_utils.py
272
274
  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.2",
20
+ version="0.40.3",
21
21
  description="A framework for writing Airbyte Connectors.",
22
22
  long_description=README,
23
23
  long_description_content_type="text/markdown",
@@ -354,6 +354,7 @@ def test_read():
354
354
  ],
355
355
  test_read_limit_reached=False,
356
356
  inferred_schema=None,
357
+ inferred_datetime_formats=None,
357
358
  latest_config_update={}
358
359
  )
359
360
 
@@ -368,6 +369,7 @@ def test_read():
368
369
  ],
369
370
  "test_read_limit_reached": False,
370
371
  "inferred_schema": None,
372
+ "inferred_datetime_formats": None,
371
373
  "latest_config_update": {}
372
374
  },
373
375
  emitted_at=1,
@@ -410,6 +412,7 @@ def test_read_returns_error_response(mock_from_exception):
410
412
  slice_descriptor=None, state=None)],
411
413
  test_read_limit_reached=False,
412
414
  inferred_schema=None,
415
+ inferred_datetime_formats={},
413
416
  latest_config_update={})
414
417
 
415
418
  expected_message = AirbyteMessage(
@@ -94,7 +94,8 @@ def test_get_grouped_messages(mock_entrypoint_read):
94
94
  "body": {"custom": "field"},
95
95
  }
96
96
  response = {"status_code": 200, "headers": {"field": "value"}, "body": '{"name": "field"}', "http_method": "GET"}
97
- expected_schema = {"$schema": "http://json-schema.org/schema#", "properties": {"name": {"type": "string"}}, "type": "object"}
97
+ expected_schema = {"$schema": "http://json-schema.org/schema#", "properties": {"name": {"type": "string"}, "date": {"type": "string"}}, "type": "object"}
98
+ expected_datetime_fields = {"date":"%Y-%m-%d"}
98
99
  expected_pages = [
99
100
  StreamReadPages(
100
101
  request=HttpRequest(
@@ -105,7 +106,7 @@ def test_get_grouped_messages(mock_entrypoint_read):
105
106
  http_method="GET",
106
107
  ),
107
108
  response=HttpResponse(status=200, headers={"field": "value"}, body='{"name": "field"}'),
108
- records=[{"name": "Shinobu Kocho"}, {"name": "Muichiro Tokito"}],
109
+ records=[{"name": "Shinobu Kocho", "date": "2023-03-03"}, {"name": "Muichiro Tokito", "date": "2023-03-04"}],
109
110
  ),
110
111
  StreamReadPages(
111
112
  request=HttpRequest(
@@ -116,7 +117,7 @@ def test_get_grouped_messages(mock_entrypoint_read):
116
117
  http_method="GET",
117
118
  ),
118
119
  response=HttpResponse(status=200, headers={"field": "value"}, body='{"name": "field"}'),
119
- records=[{"name": "Mitsuri Kanroji"}],
120
+ records=[{"name": "Mitsuri Kanroji", "date": "2023-03-05"}],
120
121
  ),
121
122
  ]
122
123
 
@@ -124,11 +125,11 @@ def test_get_grouped_messages(mock_entrypoint_read):
124
125
  [
125
126
  request_log_message(request),
126
127
  response_log_message(response),
127
- record_message("hashiras", {"name": "Shinobu Kocho"}),
128
- record_message("hashiras", {"name": "Muichiro Tokito"}),
128
+ record_message("hashiras", {"name": "Shinobu Kocho", "date": "2023-03-03"}),
129
+ record_message("hashiras", {"name": "Muichiro Tokito", "date": "2023-03-04"}),
129
130
  request_log_message(request),
130
131
  response_log_message(response),
131
- record_message("hashiras", {"name": "Mitsuri Kanroji"}),
132
+ record_message("hashiras", {"name": "Mitsuri Kanroji", "date": "2023-03-05"}),
132
133
  ]
133
134
  ))
134
135
 
@@ -138,6 +139,7 @@ def test_get_grouped_messages(mock_entrypoint_read):
138
139
  )
139
140
 
140
141
  assert actual_response.inferred_schema == expected_schema
142
+ assert actual_response.inferred_datetime_formats == expected_datetime_fields
141
143
 
142
144
  single_slice = actual_response.slices[0]
143
145
  for i, actual_page in enumerate(single_slice.pages):
@@ -0,0 +1,53 @@
1
+ #
2
+ # Copyright (c) 2023 Airbyte, Inc., all rights reserved.
3
+ #
4
+
5
+ from typing import Dict, List
6
+
7
+ import pytest
8
+ from airbyte_cdk.models.airbyte_protocol import AirbyteRecordMessage
9
+ from airbyte_cdk.utils.datetime_format_inferrer import DatetimeFormatInferrer
10
+
11
+ NOW = 1234567
12
+
13
+
14
+ @pytest.mark.parametrize(
15
+ "test_name,input_records,expected_candidate_fields",
16
+ [
17
+ ("empty", [], {}),
18
+ ("simple_match", [{"d": "2022-02-03"}], {"d": "%Y-%m-%d"}),
19
+ ("timestamp_match_integer", [{"d": 1686058051}], {"d": "%s"}),
20
+ ("timestamp_match_string", [{"d": "1686058051"}], {"d": "%s"}),
21
+ ("timestamp_no_match_integer", [{"d": 99}], {}),
22
+ ("timestamp_no_match_string", [{"d": "99999999999999999999"}], {}),
23
+ ("simple_no_match", [{"d": "20220203"}], {}),
24
+ ("multiple_match", [{"d": "2022-02-03", "e": "2022-02-03"}], {"d": "%Y-%m-%d", "e": "%Y-%m-%d"}),
25
+ (
26
+ "multiple_no_match",
27
+ [{"d": "20220203", "r": "ccc", "e": {"something-else": "2023-03-03"}, "s": ["2023-03-03"], "x": False, "y": 123}],
28
+ {},
29
+ ),
30
+ ("format_1", [{"d": "2022-02-03"}], {"d": "%Y-%m-%d"}),
31
+ ("format_2", [{"d": "2022-02-03 12:34:56"}], {"d": "%Y-%m-%d %H:%M:%S"}),
32
+ ("format_3", [{"d": "2022-02-03 12:34:56.123456+00:00"}], {"d": "%Y-%m-%d %H:%M:%S.%f+00:00"}),
33
+ ("format_4", [{"d": "2022-02-03T12:34:56.123456+0000"}], {"d": "%Y-%m-%dT%H:%M:%S.%f%z"}),
34
+ ("format_4 2", [{"d": "2022-02-03T12:34:56.000Z"}], {"d": "%Y-%m-%dT%H:%M:%S.%f%z"}),
35
+ ("format_4 2", [{"d": "2022-02-03T12:34:56.000000Z"}], {"d": "%Y-%m-%dT%H:%M:%S.%f%z"}),
36
+ ("format_6", [{"d": "03/02/2022 12:34"}], {"d": "%d/%m/%Y %H:%M"}),
37
+ ("format_7", [{"d": "2022-02"}], {"d": "%Y-%m"}),
38
+ ("format_8", [{"d": "03-02-2022"}], {"d": "%d-%m-%Y"}),
39
+ ("limit_down", [{"d": "2022-02-03", "x": "2022-02-03"}, {"d": "2022-02-03", "x": "another thing"}], {"d": "%Y-%m-%d"}),
40
+ ("limit_down all", [{"d": "2022-02-03", "x": "2022-02-03"}, {"d": "also another thing", "x": "another thing"}], {}),
41
+ ("limit_down empty", [{"d": "2022-02-03", "x": "2022-02-03"}, {}], {}),
42
+ ("limit_down unsupported type", [{"d": "2022-02-03"}, {"d": False}], {}),
43
+ ("limit_down complex type", [{"d": "2022-02-03"}, {"d": {"date": "2022-03-03"}}], {}),
44
+ ("limit_down different format", [{"d": "2022-02-03"}, {"d": 1686058051}], {}),
45
+ ("limit_down different format", [{"d": "2022-02-03"}, {"d": "2022-02-03T12:34:56.000000Z"}], {}),
46
+ ("no scope expand", [{}, {"d": "2022-02-03"}], {}),
47
+ ],
48
+ )
49
+ def test_schema_inferrer(test_name, input_records: List, expected_candidate_fields: Dict[str, str]):
50
+ inferrer = DatetimeFormatInferrer()
51
+ for record in input_records:
52
+ inferrer.accumulate(AirbyteRecordMessage(stream="abc", data=record, emitted_at=NOW))
53
+ assert inferrer.get_inferred_datetime_formats() == expected_candidate_fields
File without changes
File without changes