airbyte-cdk 0.72.1__py3-none-any.whl → 6.17.1.dev0__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (518) hide show
  1. airbyte_cdk/__init__.py +355 -6
  2. airbyte_cdk/cli/__init__.py +1 -0
  3. airbyte_cdk/cli/source_declarative_manifest/__init__.py +5 -0
  4. airbyte_cdk/cli/source_declarative_manifest/_run.py +230 -0
  5. airbyte_cdk/cli/source_declarative_manifest/spec.json +17 -0
  6. airbyte_cdk/config_observation.py +29 -10
  7. airbyte_cdk/connector.py +24 -24
  8. airbyte_cdk/connector_builder/README.md +53 -0
  9. airbyte_cdk/connector_builder/connector_builder_handler.py +37 -11
  10. airbyte_cdk/connector_builder/main.py +45 -13
  11. airbyte_cdk/connector_builder/message_grouper.py +189 -50
  12. airbyte_cdk/connector_builder/models.py +3 -2
  13. airbyte_cdk/destinations/__init__.py +4 -3
  14. airbyte_cdk/destinations/destination.py +54 -20
  15. airbyte_cdk/destinations/vector_db_based/README.md +37 -0
  16. airbyte_cdk/destinations/vector_db_based/config.py +40 -17
  17. airbyte_cdk/destinations/vector_db_based/document_processor.py +56 -17
  18. airbyte_cdk/destinations/vector_db_based/embedder.py +57 -15
  19. airbyte_cdk/destinations/vector_db_based/test_utils.py +14 -4
  20. airbyte_cdk/destinations/vector_db_based/utils.py +8 -2
  21. airbyte_cdk/destinations/vector_db_based/writer.py +24 -5
  22. airbyte_cdk/entrypoint.py +153 -44
  23. airbyte_cdk/exception_handler.py +21 -3
  24. airbyte_cdk/logger.py +30 -44
  25. airbyte_cdk/models/__init__.py +13 -2
  26. airbyte_cdk/models/airbyte_protocol.py +86 -1
  27. airbyte_cdk/models/airbyte_protocol_serializers.py +44 -0
  28. airbyte_cdk/models/file_transfer_record_message.py +13 -0
  29. airbyte_cdk/models/well_known_types.py +1 -1
  30. airbyte_cdk/sources/__init__.py +5 -1
  31. airbyte_cdk/sources/abstract_source.py +125 -79
  32. airbyte_cdk/sources/concurrent_source/__init__.py +7 -2
  33. airbyte_cdk/sources/concurrent_source/concurrent_read_processor.py +102 -36
  34. airbyte_cdk/sources/concurrent_source/concurrent_source.py +29 -36
  35. airbyte_cdk/sources/concurrent_source/concurrent_source_adapter.py +94 -10
  36. airbyte_cdk/sources/concurrent_source/stream_thread_exception.py +25 -0
  37. airbyte_cdk/sources/concurrent_source/thread_pool_manager.py +20 -14
  38. airbyte_cdk/sources/config.py +3 -2
  39. airbyte_cdk/sources/connector_state_manager.py +49 -83
  40. airbyte_cdk/sources/declarative/async_job/job.py +52 -0
  41. airbyte_cdk/sources/declarative/async_job/job_orchestrator.py +497 -0
  42. airbyte_cdk/sources/declarative/async_job/job_tracker.py +75 -0
  43. airbyte_cdk/sources/declarative/async_job/repository.py +35 -0
  44. airbyte_cdk/sources/declarative/async_job/status.py +24 -0
  45. airbyte_cdk/sources/declarative/async_job/timer.py +39 -0
  46. airbyte_cdk/sources/declarative/auth/__init__.py +2 -3
  47. airbyte_cdk/sources/declarative/auth/declarative_authenticator.py +3 -1
  48. airbyte_cdk/sources/declarative/auth/jwt.py +191 -0
  49. airbyte_cdk/sources/declarative/auth/oauth.py +60 -20
  50. airbyte_cdk/sources/declarative/auth/selective_authenticator.py +10 -2
  51. airbyte_cdk/sources/declarative/auth/token.py +28 -10
  52. airbyte_cdk/sources/declarative/auth/token_provider.py +9 -8
  53. airbyte_cdk/sources/declarative/checks/check_stream.py +16 -8
  54. airbyte_cdk/sources/declarative/checks/connection_checker.py +4 -2
  55. airbyte_cdk/sources/declarative/concurrency_level/__init__.py +7 -0
  56. airbyte_cdk/sources/declarative/concurrency_level/concurrency_level.py +50 -0
  57. airbyte_cdk/sources/declarative/concurrent_declarative_source.py +490 -0
  58. airbyte_cdk/sources/declarative/datetime/datetime_parser.py +4 -0
  59. airbyte_cdk/sources/declarative/datetime/min_max_datetime.py +26 -6
  60. airbyte_cdk/sources/declarative/declarative_component_schema.yaml +1185 -85
  61. airbyte_cdk/sources/declarative/declarative_source.py +5 -2
  62. airbyte_cdk/sources/declarative/declarative_stream.py +95 -9
  63. airbyte_cdk/sources/declarative/decoders/__init__.py +23 -2
  64. airbyte_cdk/sources/declarative/decoders/composite_raw_decoder.py +97 -0
  65. airbyte_cdk/sources/declarative/decoders/decoder.py +11 -4
  66. airbyte_cdk/sources/declarative/decoders/json_decoder.py +92 -5
  67. airbyte_cdk/sources/declarative/decoders/noop_decoder.py +21 -0
  68. airbyte_cdk/sources/declarative/decoders/pagination_decoder_decorator.py +39 -0
  69. airbyte_cdk/sources/declarative/decoders/xml_decoder.py +98 -0
  70. airbyte_cdk/sources/declarative/extractors/__init__.py +12 -1
  71. airbyte_cdk/sources/declarative/extractors/dpath_extractor.py +29 -24
  72. airbyte_cdk/sources/declarative/extractors/http_selector.py +4 -5
  73. airbyte_cdk/sources/declarative/extractors/record_extractor.py +2 -3
  74. airbyte_cdk/sources/declarative/extractors/record_filter.py +63 -8
  75. airbyte_cdk/sources/declarative/extractors/record_selector.py +85 -26
  76. airbyte_cdk/sources/declarative/extractors/response_to_file_extractor.py +177 -0
  77. airbyte_cdk/sources/declarative/extractors/type_transformer.py +55 -0
  78. airbyte_cdk/sources/declarative/incremental/__init__.py +31 -3
  79. airbyte_cdk/sources/declarative/incremental/concurrent_partition_cursor.py +346 -0
  80. airbyte_cdk/sources/declarative/incremental/datetime_based_cursor.py +156 -48
  81. airbyte_cdk/sources/declarative/incremental/declarative_cursor.py +13 -0
  82. airbyte_cdk/sources/declarative/incremental/global_substream_cursor.py +350 -0
  83. airbyte_cdk/sources/declarative/incremental/per_partition_cursor.py +173 -74
  84. airbyte_cdk/sources/declarative/incremental/per_partition_with_global.py +200 -0
  85. airbyte_cdk/sources/declarative/incremental/resumable_full_refresh_cursor.py +122 -0
  86. airbyte_cdk/sources/declarative/interpolation/filters.py +27 -1
  87. airbyte_cdk/sources/declarative/interpolation/interpolated_boolean.py +23 -5
  88. airbyte_cdk/sources/declarative/interpolation/interpolated_mapping.py +12 -8
  89. airbyte_cdk/sources/declarative/interpolation/interpolated_nested_mapping.py +13 -6
  90. airbyte_cdk/sources/declarative/interpolation/interpolated_string.py +21 -6
  91. airbyte_cdk/sources/declarative/interpolation/interpolation.py +9 -3
  92. airbyte_cdk/sources/declarative/interpolation/jinja.py +72 -37
  93. airbyte_cdk/sources/declarative/interpolation/macros.py +72 -17
  94. airbyte_cdk/sources/declarative/manifest_declarative_source.py +193 -52
  95. airbyte_cdk/sources/declarative/migrations/legacy_to_per_partition_state_migration.py +98 -0
  96. airbyte_cdk/sources/declarative/migrations/state_migration.py +24 -0
  97. airbyte_cdk/sources/declarative/models/__init__.py +1 -1
  98. airbyte_cdk/sources/declarative/models/declarative_component_schema.py +1319 -603
  99. airbyte_cdk/sources/declarative/parsers/custom_exceptions.py +2 -2
  100. airbyte_cdk/sources/declarative/parsers/manifest_component_transformer.py +26 -4
  101. airbyte_cdk/sources/declarative/parsers/manifest_reference_resolver.py +26 -15
  102. airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py +1759 -225
  103. airbyte_cdk/sources/declarative/partition_routers/__init__.py +24 -4
  104. airbyte_cdk/sources/declarative/partition_routers/async_job_partition_router.py +65 -0
  105. airbyte_cdk/sources/declarative/partition_routers/cartesian_product_stream_slicer.py +176 -0
  106. airbyte_cdk/sources/declarative/partition_routers/list_partition_router.py +39 -9
  107. airbyte_cdk/sources/declarative/partition_routers/partition_router.py +62 -0
  108. airbyte_cdk/sources/declarative/partition_routers/single_partition_router.py +15 -3
  109. airbyte_cdk/sources/declarative/partition_routers/substream_partition_router.py +222 -39
  110. airbyte_cdk/sources/declarative/requesters/error_handlers/__init__.py +19 -5
  111. airbyte_cdk/sources/declarative/requesters/error_handlers/backoff_strategies/__init__.py +3 -1
  112. airbyte_cdk/sources/declarative/requesters/error_handlers/backoff_strategies/constant_backoff_strategy.py +19 -7
  113. airbyte_cdk/sources/declarative/requesters/error_handlers/backoff_strategies/exponential_backoff_strategy.py +19 -7
  114. airbyte_cdk/sources/declarative/requesters/error_handlers/backoff_strategies/header_helper.py +4 -2
  115. airbyte_cdk/sources/declarative/requesters/error_handlers/backoff_strategies/wait_time_from_header_backoff_strategy.py +41 -9
  116. airbyte_cdk/sources/declarative/requesters/error_handlers/backoff_strategies/wait_until_time_from_header_backoff_strategy.py +29 -14
  117. airbyte_cdk/sources/declarative/requesters/error_handlers/backoff_strategy.py +5 -13
  118. airbyte_cdk/sources/declarative/requesters/error_handlers/composite_error_handler.py +32 -16
  119. airbyte_cdk/sources/declarative/requesters/error_handlers/default_error_handler.py +46 -56
  120. airbyte_cdk/sources/declarative/requesters/error_handlers/default_http_response_filter.py +40 -0
  121. airbyte_cdk/sources/declarative/requesters/error_handlers/error_handler.py +6 -32
  122. airbyte_cdk/sources/declarative/requesters/error_handlers/http_response_filter.py +119 -41
  123. airbyte_cdk/sources/declarative/requesters/http_job_repository.py +228 -0
  124. airbyte_cdk/sources/declarative/requesters/http_requester.py +98 -344
  125. airbyte_cdk/sources/declarative/requesters/paginators/__init__.py +14 -3
  126. airbyte_cdk/sources/declarative/requesters/paginators/default_paginator.py +105 -46
  127. airbyte_cdk/sources/declarative/requesters/paginators/no_pagination.py +14 -8
  128. airbyte_cdk/sources/declarative/requesters/paginators/paginator.py +19 -8
  129. airbyte_cdk/sources/declarative/requesters/paginators/strategies/__init__.py +9 -3
  130. airbyte_cdk/sources/declarative/requesters/paginators/strategies/cursor_pagination_strategy.py +53 -21
  131. airbyte_cdk/sources/declarative/requesters/paginators/strategies/offset_increment.py +42 -19
  132. airbyte_cdk/sources/declarative/requesters/paginators/strategies/page_increment.py +25 -12
  133. airbyte_cdk/sources/declarative/requesters/paginators/strategies/pagination_strategy.py +13 -10
  134. airbyte_cdk/sources/declarative/requesters/paginators/strategies/stop_condition.py +26 -13
  135. airbyte_cdk/sources/declarative/requesters/request_options/__init__.py +15 -2
  136. airbyte_cdk/sources/declarative/requesters/request_options/datetime_based_request_options_provider.py +91 -0
  137. airbyte_cdk/sources/declarative/requesters/request_options/default_request_options_provider.py +60 -0
  138. airbyte_cdk/sources/declarative/requesters/request_options/interpolated_nested_request_input_provider.py +31 -14
  139. airbyte_cdk/sources/declarative/requesters/request_options/interpolated_request_input_provider.py +27 -15
  140. airbyte_cdk/sources/declarative/requesters/request_options/interpolated_request_options_provider.py +63 -10
  141. airbyte_cdk/sources/declarative/requesters/request_options/request_options_provider.py +1 -1
  142. airbyte_cdk/sources/declarative/requesters/requester.py +9 -17
  143. airbyte_cdk/sources/declarative/resolvers/__init__.py +41 -0
  144. airbyte_cdk/sources/declarative/resolvers/components_resolver.py +55 -0
  145. airbyte_cdk/sources/declarative/resolvers/config_components_resolver.py +136 -0
  146. airbyte_cdk/sources/declarative/resolvers/http_components_resolver.py +112 -0
  147. airbyte_cdk/sources/declarative/retrievers/__init__.py +6 -2
  148. airbyte_cdk/sources/declarative/retrievers/async_retriever.py +100 -0
  149. airbyte_cdk/sources/declarative/retrievers/retriever.py +1 -3
  150. airbyte_cdk/sources/declarative/retrievers/simple_retriever.py +229 -73
  151. airbyte_cdk/sources/declarative/schema/__init__.py +14 -1
  152. airbyte_cdk/sources/declarative/schema/default_schema_loader.py +5 -3
  153. airbyte_cdk/sources/declarative/schema/dynamic_schema_loader.py +236 -0
  154. airbyte_cdk/sources/declarative/schema/json_file_schema_loader.py +8 -8
  155. airbyte_cdk/sources/declarative/spec/spec.py +12 -5
  156. airbyte_cdk/sources/declarative/stream_slicers/__init__.py +1 -2
  157. airbyte_cdk/sources/declarative/stream_slicers/declarative_partition_generator.py +88 -0
  158. airbyte_cdk/sources/declarative/stream_slicers/stream_slicer.py +9 -14
  159. airbyte_cdk/sources/declarative/transformations/add_fields.py +19 -11
  160. airbyte_cdk/sources/declarative/transformations/flatten_fields.py +52 -0
  161. airbyte_cdk/sources/declarative/transformations/keys_replace_transformation.py +61 -0
  162. airbyte_cdk/sources/declarative/transformations/keys_to_lower_transformation.py +22 -0
  163. airbyte_cdk/sources/declarative/transformations/keys_to_snake_transformation.py +68 -0
  164. airbyte_cdk/sources/declarative/transformations/remove_fields.py +13 -10
  165. airbyte_cdk/sources/declarative/transformations/transformation.py +5 -5
  166. airbyte_cdk/sources/declarative/types.py +19 -110
  167. airbyte_cdk/sources/declarative/yaml_declarative_source.py +31 -10
  168. airbyte_cdk/sources/embedded/base_integration.py +16 -5
  169. airbyte_cdk/sources/embedded/catalog.py +16 -4
  170. airbyte_cdk/sources/embedded/runner.py +19 -3
  171. airbyte_cdk/sources/embedded/tools.py +5 -2
  172. airbyte_cdk/sources/file_based/README.md +152 -0
  173. airbyte_cdk/sources/file_based/__init__.py +24 -0
  174. airbyte_cdk/sources/file_based/availability_strategy/__init__.py +9 -2
  175. airbyte_cdk/sources/file_based/availability_strategy/abstract_file_based_availability_strategy.py +22 -6
  176. airbyte_cdk/sources/file_based/availability_strategy/default_file_based_availability_strategy.py +46 -10
  177. airbyte_cdk/sources/file_based/config/abstract_file_based_spec.py +47 -10
  178. airbyte_cdk/sources/file_based/config/avro_format.py +2 -1
  179. airbyte_cdk/sources/file_based/config/csv_format.py +29 -10
  180. airbyte_cdk/sources/file_based/config/excel_format.py +18 -0
  181. airbyte_cdk/sources/file_based/config/file_based_stream_config.py +16 -4
  182. airbyte_cdk/sources/file_based/config/jsonl_format.py +2 -1
  183. airbyte_cdk/sources/file_based/config/parquet_format.py +2 -1
  184. airbyte_cdk/sources/file_based/config/unstructured_format.py +13 -5
  185. airbyte_cdk/sources/file_based/discovery_policy/__init__.py +6 -2
  186. airbyte_cdk/sources/file_based/discovery_policy/abstract_discovery_policy.py +2 -4
  187. airbyte_cdk/sources/file_based/discovery_policy/default_discovery_policy.py +7 -2
  188. airbyte_cdk/sources/file_based/exceptions.py +18 -15
  189. airbyte_cdk/sources/file_based/file_based_source.py +140 -33
  190. airbyte_cdk/sources/file_based/file_based_stream_reader.py +69 -5
  191. airbyte_cdk/sources/file_based/file_types/__init__.py +14 -1
  192. airbyte_cdk/sources/file_based/file_types/avro_parser.py +75 -24
  193. airbyte_cdk/sources/file_based/file_types/csv_parser.py +116 -34
  194. airbyte_cdk/sources/file_based/file_types/excel_parser.py +196 -0
  195. airbyte_cdk/sources/file_based/file_types/file_transfer.py +37 -0
  196. airbyte_cdk/sources/file_based/file_types/file_type_parser.py +4 -1
  197. airbyte_cdk/sources/file_based/file_types/jsonl_parser.py +24 -8
  198. airbyte_cdk/sources/file_based/file_types/parquet_parser.py +60 -18
  199. airbyte_cdk/sources/file_based/file_types/unstructured_parser.py +141 -41
  200. airbyte_cdk/sources/file_based/remote_file.py +1 -1
  201. airbyte_cdk/sources/file_based/schema_helpers.py +38 -10
  202. airbyte_cdk/sources/file_based/schema_validation_policies/__init__.py +3 -1
  203. airbyte_cdk/sources/file_based/schema_validation_policies/abstract_schema_validation_policy.py +3 -1
  204. airbyte_cdk/sources/file_based/schema_validation_policies/default_schema_validation_policies.py +16 -5
  205. airbyte_cdk/sources/file_based/stream/abstract_file_based_stream.py +50 -13
  206. airbyte_cdk/sources/file_based/stream/concurrent/adapters.py +67 -27
  207. airbyte_cdk/sources/file_based/stream/concurrent/cursor/__init__.py +5 -1
  208. airbyte_cdk/sources/file_based/stream/concurrent/cursor/abstract_concurrent_file_based_cursor.py +14 -23
  209. airbyte_cdk/sources/file_based/stream/concurrent/cursor/file_based_concurrent_cursor.py +54 -18
  210. airbyte_cdk/sources/file_based/stream/concurrent/cursor/file_based_final_state_cursor.py +21 -9
  211. airbyte_cdk/sources/file_based/stream/cursor/abstract_file_based_cursor.py +3 -1
  212. airbyte_cdk/sources/file_based/stream/cursor/default_file_based_cursor.py +27 -10
  213. airbyte_cdk/sources/file_based/stream/default_file_based_stream.py +147 -45
  214. airbyte_cdk/sources/http_logger.py +8 -3
  215. airbyte_cdk/sources/message/__init__.py +7 -1
  216. airbyte_cdk/sources/message/repository.py +18 -4
  217. airbyte_cdk/sources/source.py +42 -38
  218. airbyte_cdk/sources/streams/__init__.py +2 -2
  219. airbyte_cdk/sources/streams/availability_strategy.py +54 -3
  220. airbyte_cdk/sources/streams/call_rate.py +64 -21
  221. airbyte_cdk/sources/streams/checkpoint/__init__.py +26 -0
  222. airbyte_cdk/sources/streams/checkpoint/checkpoint_reader.py +335 -0
  223. airbyte_cdk/sources/{declarative/incremental → streams/checkpoint}/cursor.py +17 -14
  224. airbyte_cdk/sources/streams/checkpoint/per_partition_key_serializer.py +22 -0
  225. airbyte_cdk/sources/streams/checkpoint/resumable_full_refresh_cursor.py +51 -0
  226. airbyte_cdk/sources/streams/checkpoint/substream_resumable_full_refresh_cursor.py +110 -0
  227. airbyte_cdk/sources/streams/concurrent/README.md +7 -0
  228. airbyte_cdk/sources/streams/concurrent/abstract_stream.py +7 -2
  229. airbyte_cdk/sources/streams/concurrent/adapters.py +84 -75
  230. airbyte_cdk/sources/streams/concurrent/availability_strategy.py +30 -2
  231. airbyte_cdk/sources/streams/concurrent/cursor.py +298 -42
  232. airbyte_cdk/sources/streams/concurrent/default_stream.py +12 -3
  233. airbyte_cdk/sources/streams/concurrent/exceptions.py +3 -0
  234. airbyte_cdk/sources/streams/concurrent/helpers.py +14 -3
  235. airbyte_cdk/sources/streams/concurrent/partition_enqueuer.py +12 -3
  236. airbyte_cdk/sources/streams/concurrent/partition_reader.py +10 -3
  237. airbyte_cdk/sources/streams/concurrent/partitions/partition.py +1 -16
  238. airbyte_cdk/sources/streams/concurrent/partitions/stream_slicer.py +21 -0
  239. airbyte_cdk/sources/streams/concurrent/partitions/types.py +15 -5
  240. airbyte_cdk/sources/streams/concurrent/state_converters/abstract_stream_state_converter.py +109 -17
  241. airbyte_cdk/sources/streams/concurrent/state_converters/datetime_stream_state_converter.py +90 -72
  242. airbyte_cdk/sources/streams/core.py +412 -87
  243. airbyte_cdk/sources/streams/http/__init__.py +2 -1
  244. airbyte_cdk/sources/streams/http/availability_strategy.py +12 -101
  245. airbyte_cdk/sources/streams/http/error_handlers/__init__.py +22 -0
  246. airbyte_cdk/sources/streams/http/error_handlers/backoff_strategy.py +28 -0
  247. airbyte_cdk/sources/streams/http/error_handlers/default_backoff_strategy.py +17 -0
  248. airbyte_cdk/sources/streams/http/error_handlers/default_error_mapping.py +86 -0
  249. airbyte_cdk/sources/streams/http/error_handlers/error_handler.py +42 -0
  250. airbyte_cdk/sources/streams/http/error_handlers/error_message_parser.py +19 -0
  251. airbyte_cdk/sources/streams/http/error_handlers/http_status_error_handler.py +110 -0
  252. airbyte_cdk/sources/streams/http/error_handlers/json_error_message_parser.py +52 -0
  253. airbyte_cdk/sources/streams/http/error_handlers/response_models.py +65 -0
  254. airbyte_cdk/sources/streams/http/exceptions.py +27 -7
  255. airbyte_cdk/sources/streams/http/http.py +369 -246
  256. airbyte_cdk/sources/streams/http/http_client.py +531 -0
  257. airbyte_cdk/sources/streams/http/rate_limiting.py +76 -12
  258. airbyte_cdk/sources/streams/http/requests_native_auth/abstract_oauth.py +28 -9
  259. airbyte_cdk/sources/streams/http/requests_native_auth/abstract_token.py +2 -1
  260. airbyte_cdk/sources/streams/http/requests_native_auth/oauth.py +90 -35
  261. airbyte_cdk/sources/streams/http/requests_native_auth/token.py +13 -3
  262. airbyte_cdk/sources/types.py +154 -0
  263. airbyte_cdk/sources/utils/record_helper.py +36 -21
  264. airbyte_cdk/sources/utils/schema_helpers.py +13 -6
  265. airbyte_cdk/sources/utils/slice_logger.py +4 -1
  266. airbyte_cdk/sources/utils/transform.py +54 -20
  267. airbyte_cdk/sql/_util/hashing.py +34 -0
  268. airbyte_cdk/sql/_util/name_normalizers.py +92 -0
  269. airbyte_cdk/sql/constants.py +32 -0
  270. airbyte_cdk/sql/exceptions.py +235 -0
  271. airbyte_cdk/sql/secrets.py +123 -0
  272. airbyte_cdk/sql/shared/__init__.py +15 -0
  273. airbyte_cdk/sql/shared/catalog_providers.py +145 -0
  274. airbyte_cdk/sql/shared/sql_processor.py +786 -0
  275. airbyte_cdk/sql/types.py +160 -0
  276. airbyte_cdk/test/catalog_builder.py +70 -18
  277. airbyte_cdk/test/entrypoint_wrapper.py +117 -42
  278. airbyte_cdk/test/mock_http/__init__.py +1 -1
  279. airbyte_cdk/test/mock_http/matcher.py +6 -0
  280. airbyte_cdk/test/mock_http/mocker.py +57 -10
  281. airbyte_cdk/test/mock_http/request.py +19 -3
  282. airbyte_cdk/test/mock_http/response.py +3 -1
  283. airbyte_cdk/test/mock_http/response_builder.py +32 -16
  284. airbyte_cdk/test/state_builder.py +18 -10
  285. airbyte_cdk/test/utils/__init__.py +1 -0
  286. airbyte_cdk/test/utils/data.py +24 -0
  287. airbyte_cdk/test/utils/http_mocking.py +16 -0
  288. airbyte_cdk/test/utils/manifest_only_fixtures.py +60 -0
  289. airbyte_cdk/test/utils/reading.py +26 -0
  290. airbyte_cdk/utils/__init__.py +2 -1
  291. airbyte_cdk/utils/airbyte_secrets_utils.py +5 -3
  292. airbyte_cdk/utils/analytics_message.py +10 -2
  293. airbyte_cdk/utils/datetime_format_inferrer.py +4 -1
  294. airbyte_cdk/utils/event_timing.py +10 -10
  295. airbyte_cdk/utils/mapping_helpers.py +3 -1
  296. airbyte_cdk/utils/message_utils.py +20 -11
  297. airbyte_cdk/utils/print_buffer.py +75 -0
  298. airbyte_cdk/utils/schema_inferrer.py +198 -28
  299. airbyte_cdk/utils/slice_hasher.py +30 -0
  300. airbyte_cdk/utils/spec_schema_transformations.py +6 -3
  301. airbyte_cdk/utils/stream_status_utils.py +8 -1
  302. airbyte_cdk/utils/traced_exception.py +61 -21
  303. airbyte_cdk-6.17.1.dev0.dist-info/METADATA +109 -0
  304. airbyte_cdk-6.17.1.dev0.dist-info/RECORD +350 -0
  305. {airbyte_cdk-0.72.1.dist-info → airbyte_cdk-6.17.1.dev0.dist-info}/WHEEL +1 -2
  306. airbyte_cdk-6.17.1.dev0.dist-info/entry_points.txt +3 -0
  307. airbyte_cdk/sources/declarative/create_partial.py +0 -92
  308. airbyte_cdk/sources/declarative/parsers/class_types_registry.py +0 -102
  309. airbyte_cdk/sources/declarative/parsers/default_implementation_registry.py +0 -64
  310. airbyte_cdk/sources/declarative/requesters/error_handlers/response_action.py +0 -16
  311. airbyte_cdk/sources/declarative/requesters/error_handlers/response_status.py +0 -68
  312. airbyte_cdk/sources/declarative/stream_slicers/cartesian_product_stream_slicer.py +0 -114
  313. airbyte_cdk/sources/deprecated/base_source.py +0 -94
  314. airbyte_cdk/sources/deprecated/client.py +0 -99
  315. airbyte_cdk/sources/singer/__init__.py +0 -8
  316. airbyte_cdk/sources/singer/singer_helpers.py +0 -304
  317. airbyte_cdk/sources/singer/source.py +0 -186
  318. airbyte_cdk/sources/streams/concurrent/partitions/record.py +0 -23
  319. airbyte_cdk/sources/streams/http/auth/__init__.py +0 -17
  320. airbyte_cdk/sources/streams/http/auth/core.py +0 -29
  321. airbyte_cdk/sources/streams/http/auth/oauth.py +0 -113
  322. airbyte_cdk/sources/streams/http/auth/token.py +0 -47
  323. airbyte_cdk/sources/streams/utils/stream_helper.py +0 -40
  324. airbyte_cdk/sources/utils/catalog_helpers.py +0 -22
  325. airbyte_cdk/sources/utils/schema_models.py +0 -84
  326. airbyte_cdk-0.72.1.dist-info/METADATA +0 -243
  327. airbyte_cdk-0.72.1.dist-info/RECORD +0 -466
  328. airbyte_cdk-0.72.1.dist-info/top_level.txt +0 -3
  329. source_declarative_manifest/main.py +0 -29
  330. unit_tests/connector_builder/__init__.py +0 -3
  331. unit_tests/connector_builder/test_connector_builder_handler.py +0 -871
  332. unit_tests/connector_builder/test_message_grouper.py +0 -713
  333. unit_tests/connector_builder/utils.py +0 -27
  334. unit_tests/destinations/test_destination.py +0 -243
  335. unit_tests/singer/test_singer_helpers.py +0 -56
  336. unit_tests/singer/test_singer_source.py +0 -112
  337. unit_tests/sources/__init__.py +0 -0
  338. unit_tests/sources/concurrent_source/__init__.py +0 -3
  339. unit_tests/sources/concurrent_source/test_concurrent_source_adapter.py +0 -106
  340. unit_tests/sources/declarative/__init__.py +0 -3
  341. unit_tests/sources/declarative/auth/__init__.py +0 -3
  342. unit_tests/sources/declarative/auth/test_oauth.py +0 -331
  343. unit_tests/sources/declarative/auth/test_selective_authenticator.py +0 -39
  344. unit_tests/sources/declarative/auth/test_session_token_auth.py +0 -182
  345. unit_tests/sources/declarative/auth/test_token_auth.py +0 -200
  346. unit_tests/sources/declarative/auth/test_token_provider.py +0 -73
  347. unit_tests/sources/declarative/checks/__init__.py +0 -3
  348. unit_tests/sources/declarative/checks/test_check_stream.py +0 -146
  349. unit_tests/sources/declarative/decoders/__init__.py +0 -0
  350. unit_tests/sources/declarative/decoders/test_json_decoder.py +0 -16
  351. unit_tests/sources/declarative/external_component.py +0 -13
  352. unit_tests/sources/declarative/extractors/__init__.py +0 -3
  353. unit_tests/sources/declarative/extractors/test_dpath_extractor.py +0 -55
  354. unit_tests/sources/declarative/extractors/test_record_filter.py +0 -55
  355. unit_tests/sources/declarative/extractors/test_record_selector.py +0 -179
  356. unit_tests/sources/declarative/incremental/__init__.py +0 -0
  357. unit_tests/sources/declarative/incremental/test_datetime_based_cursor.py +0 -860
  358. unit_tests/sources/declarative/incremental/test_per_partition_cursor.py +0 -406
  359. unit_tests/sources/declarative/incremental/test_per_partition_cursor_integration.py +0 -332
  360. unit_tests/sources/declarative/interpolation/__init__.py +0 -3
  361. unit_tests/sources/declarative/interpolation/test_filters.py +0 -80
  362. unit_tests/sources/declarative/interpolation/test_interpolated_boolean.py +0 -40
  363. unit_tests/sources/declarative/interpolation/test_interpolated_mapping.py +0 -35
  364. unit_tests/sources/declarative/interpolation/test_interpolated_nested_mapping.py +0 -45
  365. unit_tests/sources/declarative/interpolation/test_interpolated_string.py +0 -25
  366. unit_tests/sources/declarative/interpolation/test_jinja.py +0 -240
  367. unit_tests/sources/declarative/interpolation/test_macros.py +0 -73
  368. unit_tests/sources/declarative/parsers/__init__.py +0 -3
  369. unit_tests/sources/declarative/parsers/test_manifest_component_transformer.py +0 -406
  370. unit_tests/sources/declarative/parsers/test_manifest_reference_resolver.py +0 -139
  371. unit_tests/sources/declarative/parsers/test_model_to_component_factory.py +0 -1847
  372. unit_tests/sources/declarative/parsers/testing_components.py +0 -36
  373. unit_tests/sources/declarative/partition_routers/__init__.py +0 -3
  374. unit_tests/sources/declarative/partition_routers/test_list_partition_router.py +0 -155
  375. unit_tests/sources/declarative/partition_routers/test_single_partition_router.py +0 -14
  376. unit_tests/sources/declarative/partition_routers/test_substream_partition_router.py +0 -404
  377. unit_tests/sources/declarative/requesters/__init__.py +0 -3
  378. unit_tests/sources/declarative/requesters/error_handlers/__init__.py +0 -3
  379. unit_tests/sources/declarative/requesters/error_handlers/backoff_strategies/__init__.py +0 -3
  380. unit_tests/sources/declarative/requesters/error_handlers/backoff_strategies/test_constant_backoff.py +0 -34
  381. unit_tests/sources/declarative/requesters/error_handlers/backoff_strategies/test_exponential_backoff.py +0 -36
  382. unit_tests/sources/declarative/requesters/error_handlers/backoff_strategies/test_header_helper.py +0 -38
  383. unit_tests/sources/declarative/requesters/error_handlers/backoff_strategies/test_wait_time_from_header.py +0 -35
  384. unit_tests/sources/declarative/requesters/error_handlers/backoff_strategies/test_wait_until_time_from_header.py +0 -64
  385. unit_tests/sources/declarative/requesters/error_handlers/test_composite_error_handler.py +0 -213
  386. unit_tests/sources/declarative/requesters/error_handlers/test_default_error_handler.py +0 -178
  387. unit_tests/sources/declarative/requesters/error_handlers/test_http_response_filter.py +0 -121
  388. unit_tests/sources/declarative/requesters/error_handlers/test_response_status.py +0 -44
  389. unit_tests/sources/declarative/requesters/paginators/__init__.py +0 -3
  390. unit_tests/sources/declarative/requesters/paginators/test_cursor_pagination_strategy.py +0 -64
  391. unit_tests/sources/declarative/requesters/paginators/test_default_paginator.py +0 -313
  392. unit_tests/sources/declarative/requesters/paginators/test_no_paginator.py +0 -12
  393. unit_tests/sources/declarative/requesters/paginators/test_offset_increment.py +0 -58
  394. unit_tests/sources/declarative/requesters/paginators/test_page_increment.py +0 -70
  395. unit_tests/sources/declarative/requesters/paginators/test_request_option.py +0 -43
  396. unit_tests/sources/declarative/requesters/paginators/test_stop_condition.py +0 -105
  397. unit_tests/sources/declarative/requesters/request_options/__init__.py +0 -3
  398. unit_tests/sources/declarative/requesters/request_options/test_interpolated_request_options_provider.py +0 -101
  399. unit_tests/sources/declarative/requesters/test_http_requester.py +0 -974
  400. unit_tests/sources/declarative/requesters/test_interpolated_request_input_provider.py +0 -32
  401. unit_tests/sources/declarative/retrievers/__init__.py +0 -3
  402. unit_tests/sources/declarative/retrievers/test_simple_retriever.py +0 -542
  403. unit_tests/sources/declarative/schema/__init__.py +0 -6
  404. unit_tests/sources/declarative/schema/source_test/SourceTest.py +0 -8
  405. unit_tests/sources/declarative/schema/source_test/__init__.py +0 -3
  406. unit_tests/sources/declarative/schema/test_default_schema_loader.py +0 -32
  407. unit_tests/sources/declarative/schema/test_inline_schema_loader.py +0 -19
  408. unit_tests/sources/declarative/schema/test_json_file_schema_loader.py +0 -26
  409. unit_tests/sources/declarative/states/__init__.py +0 -3
  410. unit_tests/sources/declarative/stream_slicers/__init__.py +0 -3
  411. unit_tests/sources/declarative/stream_slicers/test_cartesian_product_stream_slicer.py +0 -225
  412. unit_tests/sources/declarative/test_create_partial.py +0 -83
  413. unit_tests/sources/declarative/test_declarative_stream.py +0 -103
  414. unit_tests/sources/declarative/test_manifest_declarative_source.py +0 -1260
  415. unit_tests/sources/declarative/test_types.py +0 -39
  416. unit_tests/sources/declarative/test_yaml_declarative_source.py +0 -148
  417. unit_tests/sources/file_based/__init__.py +0 -0
  418. unit_tests/sources/file_based/availability_strategy/__init__.py +0 -0
  419. unit_tests/sources/file_based/availability_strategy/test_default_file_based_availability_strategy.py +0 -100
  420. unit_tests/sources/file_based/config/__init__.py +0 -0
  421. unit_tests/sources/file_based/config/test_abstract_file_based_spec.py +0 -28
  422. unit_tests/sources/file_based/config/test_csv_format.py +0 -34
  423. unit_tests/sources/file_based/config/test_file_based_stream_config.py +0 -84
  424. unit_tests/sources/file_based/discovery_policy/__init__.py +0 -0
  425. unit_tests/sources/file_based/discovery_policy/test_default_discovery_policy.py +0 -31
  426. unit_tests/sources/file_based/file_types/__init__.py +0 -0
  427. unit_tests/sources/file_based/file_types/test_avro_parser.py +0 -243
  428. unit_tests/sources/file_based/file_types/test_csv_parser.py +0 -546
  429. unit_tests/sources/file_based/file_types/test_jsonl_parser.py +0 -158
  430. unit_tests/sources/file_based/file_types/test_parquet_parser.py +0 -274
  431. unit_tests/sources/file_based/file_types/test_unstructured_parser.py +0 -593
  432. unit_tests/sources/file_based/helpers.py +0 -70
  433. unit_tests/sources/file_based/in_memory_files_source.py +0 -211
  434. unit_tests/sources/file_based/scenarios/__init__.py +0 -0
  435. unit_tests/sources/file_based/scenarios/avro_scenarios.py +0 -744
  436. unit_tests/sources/file_based/scenarios/check_scenarios.py +0 -220
  437. unit_tests/sources/file_based/scenarios/concurrent_incremental_scenarios.py +0 -2844
  438. unit_tests/sources/file_based/scenarios/csv_scenarios.py +0 -3105
  439. unit_tests/sources/file_based/scenarios/file_based_source_builder.py +0 -91
  440. unit_tests/sources/file_based/scenarios/incremental_scenarios.py +0 -1926
  441. unit_tests/sources/file_based/scenarios/jsonl_scenarios.py +0 -930
  442. unit_tests/sources/file_based/scenarios/parquet_scenarios.py +0 -754
  443. unit_tests/sources/file_based/scenarios/scenario_builder.py +0 -234
  444. unit_tests/sources/file_based/scenarios/unstructured_scenarios.py +0 -608
  445. unit_tests/sources/file_based/scenarios/user_input_schema_scenarios.py +0 -746
  446. unit_tests/sources/file_based/scenarios/validation_policy_scenarios.py +0 -726
  447. unit_tests/sources/file_based/stream/__init__.py +0 -0
  448. unit_tests/sources/file_based/stream/concurrent/__init__.py +0 -0
  449. unit_tests/sources/file_based/stream/concurrent/test_adapters.py +0 -362
  450. unit_tests/sources/file_based/stream/concurrent/test_file_based_concurrent_cursor.py +0 -458
  451. unit_tests/sources/file_based/stream/test_default_file_based_cursor.py +0 -310
  452. unit_tests/sources/file_based/stream/test_default_file_based_stream.py +0 -244
  453. unit_tests/sources/file_based/test_file_based_scenarios.py +0 -320
  454. unit_tests/sources/file_based/test_file_based_stream_reader.py +0 -272
  455. unit_tests/sources/file_based/test_scenarios.py +0 -253
  456. unit_tests/sources/file_based/test_schema_helpers.py +0 -346
  457. unit_tests/sources/fixtures/__init__.py +0 -3
  458. unit_tests/sources/fixtures/source_test_fixture.py +0 -153
  459. unit_tests/sources/message/__init__.py +0 -0
  460. unit_tests/sources/message/test_repository.py +0 -153
  461. unit_tests/sources/streams/__init__.py +0 -0
  462. unit_tests/sources/streams/concurrent/__init__.py +0 -3
  463. unit_tests/sources/streams/concurrent/scenarios/__init__.py +0 -3
  464. unit_tests/sources/streams/concurrent/scenarios/incremental_scenarios.py +0 -250
  465. unit_tests/sources/streams/concurrent/scenarios/stream_facade_builder.py +0 -140
  466. unit_tests/sources/streams/concurrent/scenarios/stream_facade_scenarios.py +0 -452
  467. unit_tests/sources/streams/concurrent/scenarios/test_concurrent_scenarios.py +0 -76
  468. unit_tests/sources/streams/concurrent/scenarios/thread_based_concurrent_stream_scenarios.py +0 -418
  469. unit_tests/sources/streams/concurrent/scenarios/thread_based_concurrent_stream_source_builder.py +0 -142
  470. unit_tests/sources/streams/concurrent/scenarios/utils.py +0 -55
  471. unit_tests/sources/streams/concurrent/test_adapters.py +0 -380
  472. unit_tests/sources/streams/concurrent/test_concurrent_read_processor.py +0 -684
  473. unit_tests/sources/streams/concurrent/test_cursor.py +0 -139
  474. unit_tests/sources/streams/concurrent/test_datetime_state_converter.py +0 -369
  475. unit_tests/sources/streams/concurrent/test_default_stream.py +0 -197
  476. unit_tests/sources/streams/concurrent/test_partition_enqueuer.py +0 -90
  477. unit_tests/sources/streams/concurrent/test_partition_reader.py +0 -67
  478. unit_tests/sources/streams/concurrent/test_thread_pool_manager.py +0 -106
  479. unit_tests/sources/streams/http/__init__.py +0 -0
  480. unit_tests/sources/streams/http/auth/__init__.py +0 -0
  481. unit_tests/sources/streams/http/auth/test_auth.py +0 -173
  482. unit_tests/sources/streams/http/requests_native_auth/__init__.py +0 -0
  483. unit_tests/sources/streams/http/requests_native_auth/test_requests_native_auth.py +0 -423
  484. unit_tests/sources/streams/http/test_availability_strategy.py +0 -180
  485. unit_tests/sources/streams/http/test_http.py +0 -635
  486. unit_tests/sources/streams/test_availability_strategy.py +0 -70
  487. unit_tests/sources/streams/test_call_rate.py +0 -300
  488. unit_tests/sources/streams/test_stream_read.py +0 -405
  489. unit_tests/sources/streams/test_streams_core.py +0 -184
  490. unit_tests/sources/test_abstract_source.py +0 -1442
  491. unit_tests/sources/test_concurrent_source.py +0 -112
  492. unit_tests/sources/test_config.py +0 -92
  493. unit_tests/sources/test_connector_state_manager.py +0 -482
  494. unit_tests/sources/test_http_logger.py +0 -252
  495. unit_tests/sources/test_integration_source.py +0 -86
  496. unit_tests/sources/test_source.py +0 -684
  497. unit_tests/sources/test_source_read.py +0 -460
  498. unit_tests/test/__init__.py +0 -0
  499. unit_tests/test/mock_http/__init__.py +0 -0
  500. unit_tests/test/mock_http/test_matcher.py +0 -53
  501. unit_tests/test/mock_http/test_mocker.py +0 -214
  502. unit_tests/test/mock_http/test_request.py +0 -117
  503. unit_tests/test/mock_http/test_response_builder.py +0 -177
  504. unit_tests/test/test_entrypoint_wrapper.py +0 -240
  505. unit_tests/utils/__init__.py +0 -0
  506. unit_tests/utils/test_datetime_format_inferrer.py +0 -60
  507. unit_tests/utils/test_mapping_helpers.py +0 -54
  508. unit_tests/utils/test_message_utils.py +0 -91
  509. unit_tests/utils/test_rate_limiting.py +0 -26
  510. unit_tests/utils/test_schema_inferrer.py +0 -202
  511. unit_tests/utils/test_secret_utils.py +0 -135
  512. unit_tests/utils/test_stream_status_utils.py +0 -61
  513. unit_tests/utils/test_traced_exception.py +0 -107
  514. /airbyte_cdk/sources/{deprecated → declarative/async_job}/__init__.py +0 -0
  515. {source_declarative_manifest → airbyte_cdk/sources/declarative/migrations}/__init__.py +0 -0
  516. {unit_tests/destinations → airbyte_cdk/sql}/__init__.py +0 -0
  517. {unit_tests/singer → airbyte_cdk/sql/_util}/__init__.py +0 -0
  518. {airbyte_cdk-0.72.1.dist-info → airbyte_cdk-6.17.1.dev0.dist-info}/LICENSE.txt +0 -0
airbyte_cdk/entrypoint.py CHANGED
@@ -5,6 +5,7 @@
5
5
  import argparse
6
6
  import importlib
7
7
  import ipaddress
8
+ import json
8
9
  import logging
9
10
  import os.path
10
11
  import socket
@@ -12,35 +13,48 @@ import sys
12
13
  import tempfile
13
14
  from collections import defaultdict
14
15
  from functools import wraps
15
- from typing import Any, DefaultDict, Iterable, List, Mapping, MutableMapping, Optional, Union
16
+ from typing import Any, DefaultDict, Iterable, List, Mapping, Optional
16
17
  from urllib.parse import urlparse
17
18
 
19
+ import orjson
18
20
  import requests
21
+ from requests import PreparedRequest, Response, Session
22
+
19
23
  from airbyte_cdk.connector import TConfig
20
24
  from airbyte_cdk.exception_handler import init_uncaught_exception_handler
21
25
  from airbyte_cdk.logger import init_logger
22
- from airbyte_cdk.models import AirbyteMessage, FailureType, Status, Type
23
- from airbyte_cdk.models.airbyte_protocol import AirbyteStateStats, ConnectorSpecification # type: ignore [attr-defined]
26
+ from airbyte_cdk.models import (
27
+ AirbyteConnectionStatus,
28
+ AirbyteMessage,
29
+ AirbyteMessageSerializer,
30
+ AirbyteStateStats,
31
+ ConnectorSpecification,
32
+ FailureType,
33
+ Status,
34
+ Type,
35
+ )
24
36
  from airbyte_cdk.sources import Source
25
37
  from airbyte_cdk.sources.connector_state_manager import HashableStreamDescriptor
26
38
  from airbyte_cdk.sources.utils.schema_helpers import check_config_against_spec_or_exit, split_config
39
+
40
+ # from airbyte_cdk.utils import PrintBuffer, is_cloud_environment, message_utils # add PrintBuffer back once fixed
27
41
  from airbyte_cdk.utils import is_cloud_environment, message_utils
28
42
  from airbyte_cdk.utils.airbyte_secrets_utils import get_secrets, update_secrets
29
43
  from airbyte_cdk.utils.constants import ENV_REQUEST_CACHE_PATH
30
44
  from airbyte_cdk.utils.traced_exception import AirbyteTracedException
31
- from requests import PreparedRequest, Response, Session
32
45
 
33
46
  logger = init_logger("airbyte")
34
47
 
35
48
  VALID_URL_SCHEMES = ["https"]
36
49
  CLOUD_DEPLOYMENT_MODE = "cloud"
50
+ _HAS_LOGGED_FOR_SERIALIZATION_ERROR = False
37
51
 
38
52
 
39
53
  class AirbyteEntrypoint(object):
40
54
  def __init__(self, source: Source):
41
55
  init_uncaught_exception_handler(logger)
42
56
 
43
- # deployment mode is read when instantiating the entrypoint because it is the common path shared by syncs and connector builder test requests
57
+ # Deployment mode is read when instantiating the entrypoint because it is the common path shared by syncs and connector builder test requests
44
58
  if is_cloud_environment():
45
59
  _init_internal_request_filter()
46
60
 
@@ -51,33 +65,54 @@ class AirbyteEntrypoint(object):
51
65
  def parse_args(args: List[str]) -> argparse.Namespace:
52
66
  # set up parent parsers
53
67
  parent_parser = argparse.ArgumentParser(add_help=False)
54
- parent_parser.add_argument("--debug", action="store_true", help="enables detailed debug logs related to the sync")
68
+ parent_parser.add_argument(
69
+ "--debug", action="store_true", help="enables detailed debug logs related to the sync"
70
+ )
55
71
  main_parser = argparse.ArgumentParser()
56
72
  subparsers = main_parser.add_subparsers(title="commands", dest="command")
57
73
 
58
74
  # spec
59
- subparsers.add_parser("spec", help="outputs the json configuration specification", parents=[parent_parser])
75
+ subparsers.add_parser(
76
+ "spec", help="outputs the json configuration specification", parents=[parent_parser]
77
+ )
60
78
 
61
79
  # check
62
- check_parser = subparsers.add_parser("check", help="checks the config can be used to connect", parents=[parent_parser])
80
+ check_parser = subparsers.add_parser(
81
+ "check", help="checks the config can be used to connect", parents=[parent_parser]
82
+ )
63
83
  required_check_parser = check_parser.add_argument_group("required named arguments")
64
- required_check_parser.add_argument("--config", type=str, required=True, help="path to the json configuration file")
84
+ required_check_parser.add_argument(
85
+ "--config", type=str, required=True, help="path to the json configuration file"
86
+ )
65
87
 
66
88
  # discover
67
89
  discover_parser = subparsers.add_parser(
68
- "discover", help="outputs a catalog describing the source's schema", parents=[parent_parser]
90
+ "discover",
91
+ help="outputs a catalog describing the source's schema",
92
+ parents=[parent_parser],
69
93
  )
70
94
  required_discover_parser = discover_parser.add_argument_group("required named arguments")
71
- required_discover_parser.add_argument("--config", type=str, required=True, help="path to the json configuration file")
95
+ required_discover_parser.add_argument(
96
+ "--config", type=str, required=True, help="path to the json configuration file"
97
+ )
72
98
 
73
99
  # read
74
- read_parser = subparsers.add_parser("read", help="reads the source and outputs messages to STDOUT", parents=[parent_parser])
100
+ read_parser = subparsers.add_parser(
101
+ "read", help="reads the source and outputs messages to STDOUT", parents=[parent_parser]
102
+ )
75
103
 
76
- read_parser.add_argument("--state", type=str, required=False, help="path to the json-encoded state file")
104
+ read_parser.add_argument(
105
+ "--state", type=str, required=False, help="path to the json-encoded state file"
106
+ )
77
107
  required_read_parser = read_parser.add_argument_group("required named arguments")
78
- required_read_parser.add_argument("--config", type=str, required=True, help="path to the json configuration file")
79
108
  required_read_parser.add_argument(
80
- "--catalog", type=str, required=True, help="path to the catalog used to determine which data to read"
109
+ "--config", type=str, required=True, help="path to the json configuration file"
110
+ )
111
+ required_read_parser.add_argument(
112
+ "--catalog",
113
+ type=str,
114
+ required=True,
115
+ help="path to the catalog used to determine which data to read",
81
116
  )
82
117
 
83
118
  return main_parser.parse_args(args)
@@ -96,12 +131,19 @@ class AirbyteEntrypoint(object):
96
131
 
97
132
  source_spec: ConnectorSpecification = self.source.spec(self.logger)
98
133
  try:
99
- with tempfile.TemporaryDirectory() as temp_dir:
100
- os.environ[ENV_REQUEST_CACHE_PATH] = temp_dir # set this as default directory for request_cache to store *.sqlite files
134
+ with tempfile.TemporaryDirectory(
135
+ # Cleanup can fail on Windows due to file locks. Ignore if so,
136
+ # rather than failing the whole process.
137
+ ignore_cleanup_errors=True,
138
+ ) as temp_dir:
139
+ os.environ[ENV_REQUEST_CACHE_PATH] = (
140
+ temp_dir # set this as default directory for request_cache to store *.sqlite files
141
+ )
101
142
  if cmd == "spec":
102
143
  message = AirbyteMessage(type=Type.SPEC, spec=source_spec)
103
144
  yield from [
104
- self.airbyte_message_to_string(queued_message) for queued_message in self._emit_queued_messages(self.source)
145
+ self.airbyte_message_to_string(queued_message)
146
+ for queued_message in self._emit_queued_messages(self.source)
105
147
  ]
106
148
  yield self.airbyte_message_to_string(message)
107
149
  else:
@@ -109,34 +151,68 @@ class AirbyteEntrypoint(object):
109
151
  config = self.source.configure(raw_config, temp_dir)
110
152
 
111
153
  yield from [
112
- self.airbyte_message_to_string(queued_message) for queued_message in self._emit_queued_messages(self.source)
154
+ self.airbyte_message_to_string(queued_message)
155
+ for queued_message in self._emit_queued_messages(self.source)
113
156
  ]
114
157
  if cmd == "check":
115
- yield from map(AirbyteEntrypoint.airbyte_message_to_string, self.check(source_spec, config))
158
+ yield from map(
159
+ AirbyteEntrypoint.airbyte_message_to_string,
160
+ self.check(source_spec, config),
161
+ )
116
162
  elif cmd == "discover":
117
- yield from map(AirbyteEntrypoint.airbyte_message_to_string, self.discover(source_spec, config))
163
+ yield from map(
164
+ AirbyteEntrypoint.airbyte_message_to_string,
165
+ self.discover(source_spec, config),
166
+ )
118
167
  elif cmd == "read":
119
168
  config_catalog = self.source.read_catalog(parsed_args.catalog)
120
169
  state = self.source.read_state(parsed_args.state)
121
170
 
122
- yield from map(AirbyteEntrypoint.airbyte_message_to_string, self.read(source_spec, config, config_catalog, state))
171
+ yield from map(
172
+ AirbyteEntrypoint.airbyte_message_to_string,
173
+ self.read(source_spec, config, config_catalog, state),
174
+ )
123
175
  else:
124
176
  raise Exception("Unexpected command " + cmd)
125
177
  finally:
126
- yield from [self.airbyte_message_to_string(queued_message) for queued_message in self._emit_queued_messages(self.source)]
178
+ yield from [
179
+ self.airbyte_message_to_string(queued_message)
180
+ for queued_message in self._emit_queued_messages(self.source)
181
+ ]
127
182
 
128
- def check(self, source_spec: ConnectorSpecification, config: TConfig) -> Iterable[AirbyteMessage]:
183
+ def check(
184
+ self, source_spec: ConnectorSpecification, config: TConfig
185
+ ) -> Iterable[AirbyteMessage]:
129
186
  self.set_up_secret_filter(config, source_spec.connectionSpecification)
130
187
  try:
131
188
  self.validate_connection(source_spec, config)
132
189
  except AirbyteTracedException as traced_exc:
133
190
  connection_status = traced_exc.as_connection_status_message()
191
+ # The platform uses the exit code to surface unexpected failures so we raise the exception if the failure type not a config error
192
+ # If the failure is not exceptional, we'll emit a failed connection status message and return
193
+ if traced_exc.failure_type != FailureType.config_error:
194
+ raise traced_exc
134
195
  if connection_status:
135
196
  yield from self._emit_queued_messages(self.source)
136
197
  yield connection_status
137
198
  return
138
199
 
139
- check_result = self.source.check(self.logger, config)
200
+ try:
201
+ check_result = self.source.check(self.logger, config)
202
+ except AirbyteTracedException as traced_exc:
203
+ yield traced_exc.as_airbyte_message()
204
+ # The platform uses the exit code to surface unexpected failures so we raise the exception if the failure type not a config error
205
+ # If the failure is not exceptional, we'll emit a failed connection status message and return
206
+ if traced_exc.failure_type != FailureType.config_error:
207
+ raise traced_exc
208
+ else:
209
+ yield AirbyteMessage(
210
+ type=Type.CONNECTION_STATUS,
211
+ connectionStatus=AirbyteConnectionStatus(
212
+ status=Status.FAILED, message=traced_exc.message
213
+ ),
214
+ )
215
+ return
140
216
  if check_result.status == Status.SUCCEEDED:
141
217
  self.logger.info("Check succeeded")
142
218
  else:
@@ -145,7 +221,9 @@ class AirbyteEntrypoint(object):
145
221
  yield from self._emit_queued_messages(self.source)
146
222
  yield AirbyteMessage(type=Type.CONNECTION_STATUS, connectionStatus=check_result)
147
223
 
148
- def discover(self, source_spec: ConnectorSpecification, config: TConfig) -> Iterable[AirbyteMessage]:
224
+ def discover(
225
+ self, source_spec: ConnectorSpecification, config: TConfig
226
+ ) -> Iterable[AirbyteMessage]:
149
227
  self.set_up_secret_filter(config, source_spec.connectionSpecification)
150
228
  if self.source.check_config_against_spec:
151
229
  self.validate_connection(source_spec, config)
@@ -155,32 +233,48 @@ class AirbyteEntrypoint(object):
155
233
  yield AirbyteMessage(type=Type.CATALOG, catalog=catalog)
156
234
 
157
235
  def read(
158
- self, source_spec: ConnectorSpecification, config: TConfig, catalog: Any, state: Union[list[Any], MutableMapping[str, Any]]
236
+ self, source_spec: ConnectorSpecification, config: TConfig, catalog: Any, state: list[Any]
159
237
  ) -> Iterable[AirbyteMessage]:
160
238
  self.set_up_secret_filter(config, source_spec.connectionSpecification)
161
239
  if self.source.check_config_against_spec:
162
240
  self.validate_connection(source_spec, config)
163
241
 
164
- stream_message_counter: DefaultDict[HashableStreamDescriptor, int] = defaultdict(int)
242
+ # The Airbyte protocol dictates that counts be expressed as float/double to better protect against integer overflows
243
+ stream_message_counter: DefaultDict[HashableStreamDescriptor, float] = defaultdict(float)
165
244
  for message in self.source.read(self.logger, config, catalog, state):
166
245
  yield self.handle_record_counts(message, stream_message_counter)
167
246
  for message in self._emit_queued_messages(self.source):
168
247
  yield self.handle_record_counts(message, stream_message_counter)
169
248
 
170
249
  @staticmethod
171
- def handle_record_counts(message: AirbyteMessage, stream_message_count: DefaultDict[HashableStreamDescriptor, int]) -> AirbyteMessage:
172
- if message.type == Type.RECORD:
173
- stream_message_count[message_utils.get_stream_descriptor(message)] += 1
174
-
175
- elif message.type == Type.STATE:
176
- stream_descriptor = message_utils.get_stream_descriptor(message)
177
-
178
- # Set record count from the counter onto the state message
179
- message.state.sourceStats = message.state.sourceStats or AirbyteStateStats()
180
- message.state.sourceStats.recordCount = stream_message_count.get(stream_descriptor, 0)
250
+ def handle_record_counts(
251
+ message: AirbyteMessage, stream_message_count: DefaultDict[HashableStreamDescriptor, float]
252
+ ) -> AirbyteMessage:
253
+ match message.type:
254
+ case Type.RECORD:
255
+ if message.record is None:
256
+ raise ValueError("Record message must have a record attribute")
257
+
258
+ stream_message_count[
259
+ HashableStreamDescriptor(
260
+ name=message.record.stream, # type: ignore[union-attr] # record has `stream`
261
+ namespace=message.record.namespace, # type: ignore[union-attr] # record has `namespace`
262
+ )
263
+ ] += 1.0
264
+ case Type.STATE:
265
+ if message.state is None:
266
+ raise ValueError("State message must have a state attribute")
267
+
268
+ stream_descriptor = message_utils.get_stream_descriptor(message)
269
+
270
+ # Set record count from the counter onto the state message
271
+ message.state.sourceStats = message.state.sourceStats or AirbyteStateStats() # type: ignore[union-attr] # state has `sourceStats`
272
+ message.state.sourceStats.recordCount = stream_message_count.get( # type: ignore[union-attr] # state has `sourceStats`
273
+ stream_descriptor, 0.0
274
+ )
181
275
 
182
- # Reset the counter
183
- stream_message_count[stream_descriptor] = 0
276
+ # Reset the counter
277
+ stream_message_count[stream_descriptor] = 0.0
184
278
  return message
185
279
 
186
280
  @staticmethod
@@ -198,8 +292,18 @@ class AirbyteEntrypoint(object):
198
292
  update_secrets(config_secrets)
199
293
 
200
294
  @staticmethod
201
- def airbyte_message_to_string(airbyte_message: AirbyteMessage) -> Any:
202
- return airbyte_message.json(exclude_unset=True)
295
+ def airbyte_message_to_string(airbyte_message: AirbyteMessage) -> str:
296
+ global _HAS_LOGGED_FOR_SERIALIZATION_ERROR
297
+ serialized_message = AirbyteMessageSerializer.dump(airbyte_message)
298
+ try:
299
+ return orjson.dumps(serialized_message).decode()
300
+ except Exception as exception:
301
+ if not _HAS_LOGGED_FOR_SERIALIZATION_ERROR:
302
+ logger.warning(
303
+ f"There was an error during the serialization of an AirbyteMessage: `{exception}`. This might impact the sync performances."
304
+ )
305
+ _HAS_LOGGED_FOR_SERIALIZATION_ERROR = True
306
+ return json.dumps(serialized_message)
203
307
 
204
308
  @classmethod
205
309
  def extract_state(cls, args: List[str]) -> Optional[Any]:
@@ -231,10 +335,13 @@ class AirbyteEntrypoint(object):
231
335
  def launch(source: Source, args: List[str]) -> None:
232
336
  source_entrypoint = AirbyteEntrypoint(source)
233
337
  parsed_args = source_entrypoint.parse_args(args)
338
+ # temporarily removes the PrintBuffer because we're seeing weird print behavior for concurrent syncs
339
+ # Refer to: https://github.com/airbytehq/oncall/issues/6235
340
+ # with PrintBuffer():
234
341
  for message in source_entrypoint.run(parsed_args):
235
342
  # simply printing is creating issues for concurrent CDK as Python uses different two instructions to print: one for the message and
236
343
  # the other for the break line. Adding `\n` to the message ensure that both are printed at the same time
237
- print(f"{message}\n", end="")
344
+ print(f"{message}\n", end="", flush=True)
238
345
 
239
346
 
240
347
  def _init_internal_request_filter() -> None:
@@ -254,7 +361,9 @@ def _init_internal_request_filter() -> None:
254
361
  )
255
362
 
256
363
  if not parsed_url.hostname:
257
- raise requests.exceptions.InvalidURL("Invalid URL specified: The endpoint that data is being requested from is not a valid URL")
364
+ raise requests.exceptions.InvalidURL(
365
+ "Invalid URL specified: The endpoint that data is being requested from is not a valid URL"
366
+ )
258
367
 
259
368
  try:
260
369
  is_private = _is_private_url(parsed_url.hostname, parsed_url.port) # type: ignore [arg-type]
@@ -5,12 +5,15 @@
5
5
  import logging
6
6
  import sys
7
7
  from types import TracebackType
8
- from typing import Any, Optional
8
+ from typing import Any, List, Mapping, Optional
9
9
 
10
+ from airbyte_cdk.utils.airbyte_secrets_utils import filter_secrets
10
11
  from airbyte_cdk.utils.traced_exception import AirbyteTracedException
11
12
 
12
13
 
13
- def assemble_uncaught_exception(exception_type: type[BaseException], exception_value: BaseException) -> AirbyteTracedException:
14
+ def assemble_uncaught_exception(
15
+ exception_type: type[BaseException], exception_value: BaseException
16
+ ) -> AirbyteTracedException:
14
17
  if issubclass(exception_type, AirbyteTracedException):
15
18
  return exception_value # type: ignore # validated as part of the previous line
16
19
  return AirbyteTracedException.from_exception(exception_value)
@@ -22,7 +25,11 @@ def init_uncaught_exception_handler(logger: logging.Logger) -> None:
22
25
  printed to the console without having secrets removed.
23
26
  """
24
27
 
25
- def hook_fn(exception_type: type[BaseException], exception_value: BaseException, traceback_: Optional[TracebackType]) -> Any:
28
+ def hook_fn(
29
+ exception_type: type[BaseException],
30
+ exception_value: BaseException,
31
+ traceback_: Optional[TracebackType],
32
+ ) -> Any:
26
33
  # For developer ergonomics, we want to see the stack trace in the logs when we do a ctrl-c
27
34
  if issubclass(exception_type, KeyboardInterrupt):
28
35
  sys.__excepthook__(exception_type, exception_value, traceback_)
@@ -36,3 +43,14 @@ def init_uncaught_exception_handler(logger: logging.Logger) -> None:
36
43
  traced_exc.emit_message()
37
44
 
38
45
  sys.excepthook = hook_fn
46
+
47
+
48
+ def generate_failed_streams_error_message(stream_failures: Mapping[str, List[Exception]]) -> str:
49
+ failures = "\n".join(
50
+ [
51
+ f"{stream}: {filter_secrets(exception.__repr__())}"
52
+ for stream, exceptions in stream_failures.items()
53
+ for exception in exceptions
54
+ ]
55
+ )
56
+ return f"During the sync, the following streams did not sync successfully: {failures}"
airbyte_cdk/logger.py CHANGED
@@ -5,12 +5,18 @@
5
5
  import json
6
6
  import logging
7
7
  import logging.config
8
- import traceback
9
- from typing import Tuple
8
+ from typing import Any, Callable, Mapping, Optional, Tuple
10
9
 
11
- from airbyte_cdk.models import AirbyteLogMessage, AirbyteMessage
10
+ import orjson
11
+
12
+ from airbyte_cdk.models import (
13
+ AirbyteLogMessage,
14
+ AirbyteMessage,
15
+ AirbyteMessageSerializer,
16
+ Level,
17
+ Type,
18
+ )
12
19
  from airbyte_cdk.utils.airbyte_secrets_utils import filter_secrets
13
- from deprecated import deprecated
14
20
 
15
21
  LOGGING_CONFIG = {
16
22
  "version": 1,
@@ -31,7 +37,7 @@ LOGGING_CONFIG = {
31
37
  }
32
38
 
33
39
 
34
- def init_logger(name: str = None):
40
+ def init_logger(name: Optional[str] = None) -> logging.Logger:
35
41
  """Initial set up of logger"""
36
42
  logger = logging.getLogger(name)
37
43
  logger.setLevel(logging.INFO)
@@ -39,33 +45,43 @@ def init_logger(name: str = None):
39
45
  return logger
40
46
 
41
47
 
48
+ def lazy_log(logger: logging.Logger, level: int, lazy_log_provider: Callable[[], str]) -> None:
49
+ """
50
+ This method ensure that the processing of the log message is only done if the logger is enabled for the log level.
51
+ """
52
+ if logger.isEnabledFor(level):
53
+ logger.log(level, lazy_log_provider())
54
+
55
+
42
56
  class AirbyteLogFormatter(logging.Formatter):
43
57
  """Output log records using AirbyteMessage"""
44
58
 
45
59
  # Transforming Python log levels to Airbyte protocol log levels
46
60
  level_mapping = {
47
- logging.FATAL: "FATAL",
48
- logging.ERROR: "ERROR",
49
- logging.WARNING: "WARN",
50
- logging.INFO: "INFO",
51
- logging.DEBUG: "DEBUG",
61
+ logging.FATAL: Level.FATAL,
62
+ logging.ERROR: Level.ERROR,
63
+ logging.WARNING: Level.WARN,
64
+ logging.INFO: Level.INFO,
65
+ logging.DEBUG: Level.DEBUG,
52
66
  }
53
67
 
54
68
  def format(self, record: logging.LogRecord) -> str:
55
69
  """Return a JSON representation of the log message"""
56
70
  airbyte_level = self.level_mapping.get(record.levelno, "INFO")
57
- if airbyte_level == "DEBUG":
71
+ if airbyte_level == Level.DEBUG:
58
72
  extras = self.extract_extra_args_from_record(record)
59
73
  debug_dict = {"type": "DEBUG", "message": record.getMessage(), "data": extras}
60
74
  return filter_secrets(json.dumps(debug_dict))
61
75
  else:
62
76
  message = super().format(record)
63
77
  message = filter_secrets(message)
64
- log_message = AirbyteMessage(type="LOG", log=AirbyteLogMessage(level=airbyte_level, message=message))
65
- return log_message.json(exclude_unset=True)
78
+ log_message = AirbyteMessage(
79
+ type=Type.LOG, log=AirbyteLogMessage(level=airbyte_level, message=message)
80
+ )
81
+ return orjson.dumps(AirbyteMessageSerializer.dump(log_message)).decode()
66
82
 
67
83
  @staticmethod
68
- def extract_extra_args_from_record(record: logging.LogRecord):
84
+ def extract_extra_args_from_record(record: logging.LogRecord) -> Mapping[str, Any]:
69
85
  """
70
86
  The python logger conflates default args with extra args. We use an empty log record and set operations
71
87
  to isolate fields passed to the log record via extra by the developer.
@@ -88,33 +104,3 @@ def log_by_prefix(msg: str, default_level: str) -> Tuple[int, str]:
88
104
  rendered_message = msg
89
105
 
90
106
  return log_level, rendered_message
91
-
92
-
93
- @deprecated(version="0.1.47", reason="Use logging.getLogger('airbyte') instead")
94
- class AirbyteLogger:
95
- def log(self, level, message):
96
- log_record = AirbyteLogMessage(level=level, message=message)
97
- log_message = AirbyteMessage(type="LOG", log=log_record)
98
- print(log_message.json(exclude_unset=True))
99
-
100
- def fatal(self, message):
101
- self.log("FATAL", message)
102
-
103
- def exception(self, message):
104
- message = f"{message}\n{traceback.format_exc()}"
105
- self.error(message)
106
-
107
- def error(self, message):
108
- self.log("ERROR", message)
109
-
110
- def warn(self, message):
111
- self.log("WARN", message)
112
-
113
- def info(self, message):
114
- self.log("INFO", message)
115
-
116
- def debug(self, message):
117
- self.log("DEBUG", message)
118
-
119
- def trace(self, message):
120
- self.log("TRACE", message)
@@ -21,10 +21,13 @@ from .airbyte_protocol import (
21
21
  AirbyteRecordMessage,
22
22
  AirbyteStateBlob,
23
23
  AirbyteStateMessage,
24
+ AirbyteStateStats,
24
25
  AirbyteStateType,
25
26
  AirbyteStream,
26
27
  AirbyteStreamState,
27
28
  AirbyteStreamStatus,
29
+ AirbyteStreamStatusReason,
30
+ AirbyteStreamStatusReasonType,
28
31
  AirbyteStreamStatusTraceMessage,
29
32
  AirbyteTraceMessage,
30
33
  AuthFlowType,
@@ -36,22 +39,30 @@ from .airbyte_protocol import (
36
39
  FailureType,
37
40
  Level,
38
41
  OAuthConfigSpecification,
42
+ OauthConnectorInputSpecification,
39
43
  OrchestratorType,
44
+ State,
40
45
  Status,
41
46
  StreamDescriptor,
42
47
  SyncMode,
43
48
  TraceType,
44
49
  Type,
45
50
  )
51
+ from .airbyte_protocol_serializers import (
52
+ AirbyteMessageSerializer,
53
+ AirbyteStateMessageSerializer,
54
+ AirbyteStreamStateSerializer,
55
+ ConfiguredAirbyteCatalogSerializer,
56
+ ConfiguredAirbyteStreamSerializer,
57
+ ConnectorSpecificationSerializer,
58
+ )
46
59
  from .well_known_types import (
47
60
  BinaryData,
48
61
  Boolean,
49
62
  Date,
50
63
  Integer,
51
- IntegerEnum,
52
64
  Model,
53
65
  Number,
54
- NumberEnum,
55
66
  String,
56
67
  TimestampWithoutTimezone,
57
68
  TimestampWithTimezone,
@@ -2,4 +2,89 @@
2
2
  # Copyright (c) 2023 Airbyte, Inc., all rights reserved.
3
3
  #
4
4
 
5
- from airbyte_protocol.models import *
5
+ from dataclasses import InitVar, dataclass
6
+ from typing import Annotated, Any, Dict, List, Mapping, Optional, Union
7
+
8
+ from airbyte_protocol_dataclasses.models import * # noqa: F403 # Allow '*'
9
+ from serpyco_rs.metadata import Alias
10
+
11
+ from airbyte_cdk.models.file_transfer_record_message import AirbyteFileTransferRecordMessage
12
+
13
+ # ruff: noqa: F405 # ignore fuzzy import issues with 'import *'
14
+
15
+
16
+ @dataclass
17
+ class AirbyteStateBlob:
18
+ """
19
+ A dataclass that dynamically sets attributes based on provided keyword arguments and positional arguments.
20
+ Used to "mimic" pydantic Basemodel with ConfigDict(extra='allow') option.
21
+
22
+ The `AirbyteStateBlob` class allows for flexible instantiation by accepting any number of keyword arguments
23
+ and positional arguments. These are used to dynamically update the instance's attributes. This class is useful
24
+ in scenarios where the attributes of an object are not known until runtime and need to be set dynamically.
25
+
26
+ Attributes:
27
+ kwargs (InitVar[Mapping[str, Any]]): A dictionary of keyword arguments used to set attributes dynamically.
28
+
29
+ Methods:
30
+ __init__(*args: Any, **kwargs: Any) -> None:
31
+ Initializes the `AirbyteStateBlob` by setting attributes from the provided arguments.
32
+
33
+ __eq__(other: object) -> bool:
34
+ Checks equality between two `AirbyteStateBlob` instances based on their internal dictionaries.
35
+ Returns `False` if the other object is not an instance of `AirbyteStateBlob`.
36
+ """
37
+
38
+ kwargs: InitVar[Mapping[str, Any]]
39
+
40
+ def __init__(self, *args: Any, **kwargs: Any) -> None:
41
+ # Set any attribute passed in through kwargs
42
+ for arg in args:
43
+ self.__dict__.update(arg)
44
+ for key, value in kwargs.items():
45
+ setattr(self, key, value)
46
+
47
+ def __eq__(self, other: object) -> bool:
48
+ return (
49
+ False
50
+ if not isinstance(other, AirbyteStateBlob)
51
+ else bool(self.__dict__ == other.__dict__)
52
+ )
53
+
54
+
55
+ # The following dataclasses have been redeclared to include the new version of AirbyteStateBlob
56
+ @dataclass
57
+ class AirbyteStreamState:
58
+ stream_descriptor: StreamDescriptor # type: ignore [name-defined]
59
+ stream_state: Optional[AirbyteStateBlob] = None
60
+
61
+
62
+ @dataclass
63
+ class AirbyteGlobalState:
64
+ stream_states: List[AirbyteStreamState]
65
+ shared_state: Optional[AirbyteStateBlob] = None
66
+
67
+
68
+ @dataclass
69
+ class AirbyteStateMessage:
70
+ type: Optional[AirbyteStateType] = None # type: ignore [name-defined]
71
+ stream: Optional[AirbyteStreamState] = None
72
+ global_: Annotated[AirbyteGlobalState | None, Alias("global")] = (
73
+ None # "global" is a reserved keyword in python ⇒ Alias is used for (de-)serialization
74
+ )
75
+ data: Optional[Dict[str, Any]] = None
76
+ sourceStats: Optional[AirbyteStateStats] = None # type: ignore [name-defined]
77
+ destinationStats: Optional[AirbyteStateStats] = None # type: ignore [name-defined]
78
+
79
+
80
+ @dataclass
81
+ class AirbyteMessage:
82
+ type: Type # type: ignore [name-defined]
83
+ log: Optional[AirbyteLogMessage] = None # type: ignore [name-defined]
84
+ spec: Optional[ConnectorSpecification] = None # type: ignore [name-defined]
85
+ connectionStatus: Optional[AirbyteConnectionStatus] = None # type: ignore [name-defined]
86
+ catalog: Optional[AirbyteCatalog] = None # type: ignore [name-defined]
87
+ record: Optional[Union[AirbyteFileTransferRecordMessage, AirbyteRecordMessage]] = None # type: ignore [name-defined]
88
+ state: Optional[AirbyteStateMessage] = None
89
+ trace: Optional[AirbyteTraceMessage] = None # type: ignore [name-defined]
90
+ control: Optional[AirbyteControlMessage] = None # type: ignore [name-defined]