airbyte-cdk 6.34.0.dev0__py3-none-any.whl → 6.34.0.dev2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. airbyte_cdk/connector_builder/connector_builder_handler.py +16 -12
  2. airbyte_cdk/connector_builder/test_reader/__init__.py +7 -0
  3. airbyte_cdk/connector_builder/test_reader/helpers.py +591 -0
  4. airbyte_cdk/connector_builder/test_reader/message_grouper.py +160 -0
  5. airbyte_cdk/connector_builder/test_reader/reader.py +441 -0
  6. airbyte_cdk/connector_builder/test_reader/types.py +75 -0
  7. airbyte_cdk/entrypoint.py +6 -6
  8. airbyte_cdk/logger.py +1 -4
  9. airbyte_cdk/sources/declarative/incremental/concurrent_partition_cursor.py +122 -38
  10. airbyte_cdk/sources/declarative/incremental/datetime_based_cursor.py +5 -0
  11. airbyte_cdk/sources/declarative/requesters/paginators/default_paginator.py +10 -0
  12. airbyte_cdk/sources/file_based/config/abstract_file_based_spec.py +2 -1
  13. airbyte_cdk/sources/file_based/config/validate_config_transfer_modes.py +81 -0
  14. airbyte_cdk/sources/file_based/file_based_source.py +70 -37
  15. airbyte_cdk/sources/file_based/file_based_stream_reader.py +107 -12
  16. airbyte_cdk/sources/file_based/stream/__init__.py +10 -1
  17. airbyte_cdk/sources/file_based/stream/identities_stream.py +47 -0
  18. airbyte_cdk/sources/file_based/stream/permissions_file_based_stream.py +85 -0
  19. airbyte_cdk/sources/specs/transfer_modes.py +26 -0
  20. airbyte_cdk/sources/streams/permissions/identities_stream.py +75 -0
  21. airbyte_cdk/test/mock_http/mocker.py +9 -1
  22. airbyte_cdk/test/mock_http/response.py +6 -3
  23. airbyte_cdk/utils/mapping_helpers.py +43 -2
  24. airbyte_cdk/utils/print_buffer.py +0 -4
  25. {airbyte_cdk-6.34.0.dev0.dist-info → airbyte_cdk-6.34.0.dev2.dist-info}/METADATA +1 -1
  26. {airbyte_cdk-6.34.0.dev0.dist-info → airbyte_cdk-6.34.0.dev2.dist-info}/RECORD +30 -21
  27. airbyte_cdk/connector_builder/message_grouper.py +0 -448
  28. {airbyte_cdk-6.34.0.dev0.dist-info → airbyte_cdk-6.34.0.dev2.dist-info}/LICENSE.txt +0 -0
  29. {airbyte_cdk-6.34.0.dev0.dist-info → airbyte_cdk-6.34.0.dev2.dist-info}/LICENSE_SHORT +0 -0
  30. {airbyte_cdk-6.34.0.dev0.dist-info → airbyte_cdk-6.34.0.dev2.dist-info}/WHEEL +0 -0
  31. {airbyte_cdk-6.34.0.dev0.dist-info → airbyte_cdk-6.34.0.dev2.dist-info}/entry_points.txt +0 -0
@@ -7,10 +7,14 @@ airbyte_cdk/config_observation.py,sha256=7SSPxtN0nXPkm4euGNcTTr1iLbwUL01jy-24V1H
7
7
  airbyte_cdk/connector.py,sha256=bO23kdGRkl8XKFytOgrrWFc_VagteTHVEF6IsbizVkM,4224
8
8
  airbyte_cdk/connector_builder/README.md,sha256=Hw3wvVewuHG9-QgsAq1jDiKuLlStDxKBz52ftyNRnBw,1665
9
9
  airbyte_cdk/connector_builder/__init__.py,sha256=4Hw-PX1-VgESLF16cDdvuYCzGJtHntThLF4qIiULWeo,61
10
- airbyte_cdk/connector_builder/connector_builder_handler.py,sha256=CZX1tdWYLdPE_2XtH2KnFNsHrqvWNxsotzTsKii0vrQ,4285
10
+ airbyte_cdk/connector_builder/connector_builder_handler.py,sha256=BntqkP63RBPvGCtB3CrLLtYplfSlBR42kwXyyk4YGas,4268
11
11
  airbyte_cdk/connector_builder/main.py,sha256=ubAPE0Oo5gjZOa-KMtLLJQkc8_inUpFR3sIb2DEh2No,3722
12
- airbyte_cdk/connector_builder/message_grouper.py,sha256=Xckskpqe9kbUByaKVmPsfTKxuyI2FHt8k4NZ4p8xo_I,19813
13
12
  airbyte_cdk/connector_builder/models.py,sha256=uCHpOdJx2PyZtIqk-mt9eSVuFMQoEqrW-9sjCz0Z-AQ,1500
13
+ airbyte_cdk/connector_builder/test_reader/__init__.py,sha256=iTwBMoI9vaJotEgpqZbFjlxRcbxXYypSVJ9YxeHk7wc,120
14
+ airbyte_cdk/connector_builder/test_reader/helpers.py,sha256=niu_EhzwVXnvtzj2Rf_unrxqLRC4Twbe-t17HyNoRJY,23662
15
+ airbyte_cdk/connector_builder/test_reader/message_grouper.py,sha256=L0xKpWQhfRecKblI3uYO9twPTPJYJzlOhK2P8zHWXRU,6487
16
+ airbyte_cdk/connector_builder/test_reader/reader.py,sha256=GurMB4ITO_PntvhIHSJkXbhynLilI4DObY5A2axavXo,20667
17
+ airbyte_cdk/connector_builder/test_reader/types.py,sha256=jP28aOlCS8Q6V7jMksfJKsuAJ-m2dNYiXaUjYvb0DBA,2404
14
18
  airbyte_cdk/destinations/__init__.py,sha256=FyDp28PT_YceJD5HDFhA-mrGfX9AONIyMQ4d68CHNxQ,213
15
19
  airbyte_cdk/destinations/destination.py,sha256=CIq-yb8C_0QvcKCtmStaHfiqn53GEfRAIGGCkJhKP1Q,5880
16
20
  airbyte_cdk/destinations/vector_db_based/README.md,sha256=QAe8c_1Afme4r2TCE10cTSaxUE3zgCBuArSuRQqK8tA,2115
@@ -22,9 +26,9 @@ airbyte_cdk/destinations/vector_db_based/indexer.py,sha256=beiSi2Uu67EoTr7yQSaCJ
22
26
  airbyte_cdk/destinations/vector_db_based/test_utils.py,sha256=MkqLiOJ5QyKbV4rNiJhe-BHM7FD-ADHQ4bQGf4c5lRY,1932
23
27
  airbyte_cdk/destinations/vector_db_based/utils.py,sha256=FOyEo8Lc-fY8UyhpCivhZtIqBRyxf3cUt6anmK03fUY,1127
24
28
  airbyte_cdk/destinations/vector_db_based/writer.py,sha256=nZ00xPiohElJmYktEZZIhr0m5EDETCHGhg0Lb2S7A20,5095
25
- airbyte_cdk/entrypoint.py,sha256=NRJv5BNZRSUEVTmNBa9N7ih6fW5sg4DwL0nkB9kI99Y,18570
29
+ airbyte_cdk/entrypoint.py,sha256=xFLY2PV8mKXUaeBAknczbK6plrs4_B1WdWA6K3iaRJI,18555
26
30
  airbyte_cdk/exception_handler.py,sha256=D_doVl3Dt60ASXlJsfviOCswxGyKF2q0RL6rif3fNks,2013
27
- airbyte_cdk/logger.py,sha256=1cURbvawbunCAV178q-XhTHcbAQZTSf07WhU7U9AXWU,3744
31
+ airbyte_cdk/logger.py,sha256=qi4UGuSYQQGaFaTVJlMD9lLppwqLXt1XBhwSXo-Q5IA,3660
28
32
  airbyte_cdk/models/__init__.py,sha256=MOTiuML2wShBaMSIwikdjyye2uUWBjo4J1QFSbnoiM4,2075
29
33
  airbyte_cdk/models/airbyte_protocol.py,sha256=MCmLir67-hF12YM5OKzeGbWrlxr7ChG_OQSE1xG8EIU,3748
30
34
  airbyte_cdk/models/airbyte_protocol_serializers.py,sha256=s6SaFB2CMrG_7jTQGn_fhFbQ1FUxhCxf5kq2RWGHMVI,1749
@@ -88,8 +92,8 @@ airbyte_cdk/sources/declarative/extractors/record_selector.py,sha256=HCqx7IyENM_
88
92
  airbyte_cdk/sources/declarative/extractors/response_to_file_extractor.py,sha256=LhqGDfX06_dDYLKsIVnwQ_nAWCln-v8PV7Wgt_QVeTI,6533
89
93
  airbyte_cdk/sources/declarative/extractors/type_transformer.py,sha256=d6Y2Rfg8pMVEEnHllfVksWZdNVOU55yk34O03dP9muY,1626
90
94
  airbyte_cdk/sources/declarative/incremental/__init__.py,sha256=U1oZKtBaEC6IACmvziY9Wzg7Z8EgF4ZuR7NwvjlB_Sk,1255
91
- airbyte_cdk/sources/declarative/incremental/concurrent_partition_cursor.py,sha256=5dbO47TFmC5Oz8TZ8DKXwXeZElz70xy2v2HJlZr5qVs,17751
92
- airbyte_cdk/sources/declarative/incremental/datetime_based_cursor.py,sha256=5Bl_2EeA4as0e3J23Yxp8Q8BXzh0nJ2NcGSgj3V0h2o,21954
95
+ airbyte_cdk/sources/declarative/incremental/concurrent_partition_cursor.py,sha256=T4a-WMMFzPNyMpt-aNyw-eoW90hZNO3M2-Sy57jYpCw,21418
96
+ airbyte_cdk/sources/declarative/incremental/datetime_based_cursor.py,sha256=Rbe6lJLTtZ5en33MwZiB9-H9-AwDMNHgwBZs8EqhYqk,22172
93
97
  airbyte_cdk/sources/declarative/incremental/declarative_cursor.py,sha256=5Bhw9VRPyIuCaD0wmmq_L3DZsa-rJgtKSEUzSd8YYD0,536
94
98
  airbyte_cdk/sources/declarative/incremental/global_substream_cursor.py,sha256=9HO-QbL9akvjq2NP7l498RwLA4iQZlBMQW1tZbt34I8,15943
95
99
  airbyte_cdk/sources/declarative/incremental/per_partition_cursor.py,sha256=9IAJTCiRUXvhFFz-IhZtYh_KfAjLHqthsYf2jErQRls,17728
@@ -141,7 +145,7 @@ airbyte_cdk/sources/declarative/requesters/error_handlers/http_response_filter.p
141
145
  airbyte_cdk/sources/declarative/requesters/http_job_repository.py,sha256=3GtOefPH08evlSUxaILkiKLTHbIspFY4qd5B3ZqNE60,10063
142
146
  airbyte_cdk/sources/declarative/requesters/http_requester.py,sha256=Ek5hS60-CYjvEaFD-bI7qA-bPgbOPb9hTbMBU4n5zNs,14994
143
147
  airbyte_cdk/sources/declarative/requesters/paginators/__init__.py,sha256=uArbKs9JKNCt7t9tZoeWwjDpyI1HoPp29FNW0JzvaEM,644
144
- airbyte_cdk/sources/declarative/requesters/paginators/default_paginator.py,sha256=dSm_pKGOZjzvg-X_Vif-MjrnlUG23fCa69bocq8dVIs,11693
148
+ airbyte_cdk/sources/declarative/requesters/paginators/default_paginator.py,sha256=ZW4lwWNAzb4zL0jKc-HjowP5-y0Zg9xi0YlK6tkx_XY,12057
145
149
  airbyte_cdk/sources/declarative/requesters/paginators/no_pagination.py,sha256=j6j9QRPaTbKQ2N661RFVKthhkWiodEp6ut0tKeEd0Ng,2019
146
150
  airbyte_cdk/sources/declarative/requesters/paginators/paginator.py,sha256=OlN-y0PEOMzlUNUh3pzonoTpIJpGwkP4ibFengvpLVU,2230
147
151
  airbyte_cdk/sources/declarative/requesters/paginators/strategies/__init__.py,sha256=2gly8fuZpDNwtu1Qg6oE2jBLGqQRdzSLJdnpk_iDV6I,767
@@ -201,7 +205,7 @@ airbyte_cdk/sources/file_based/availability_strategy/__init__.py,sha256=ddKQfUmk
201
205
  airbyte_cdk/sources/file_based/availability_strategy/abstract_file_based_availability_strategy.py,sha256=01Nd4b7ERAbp-OZo_8rrAzFXWPTMwr02SnWiN17nx8Q,2363
202
206
  airbyte_cdk/sources/file_based/availability_strategy/default_file_based_availability_strategy.py,sha256=j9T5TimfWFUz7nqsaj-83G3xWmDpsmeSbDnaUNmz0UM,5849
203
207
  airbyte_cdk/sources/file_based/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
204
- airbyte_cdk/sources/file_based/config/abstract_file_based_spec.py,sha256=gXlZwnEKLWknnK_n7j14lANgR6vkqhlLJ-G3rRu-ox4,6897
208
+ airbyte_cdk/sources/file_based/config/abstract_file_based_spec.py,sha256=purspcxMNWLhGunaqVJa9TISMZK7vlQSwdz4zykFWNA,6989
205
209
  airbyte_cdk/sources/file_based/config/avro_format.py,sha256=NxTF96ewzn6HuhgodsY7Rpb-ybr1ZEWW5d4Vid64g5A,716
206
210
  airbyte_cdk/sources/file_based/config/csv_format.py,sha256=NWekkyT8dTwiVK0mwa_krQD4FJPHSDfILo8kPAg3-Vs,8006
207
211
  airbyte_cdk/sources/file_based/config/excel_format.py,sha256=9qAmTsT6SoVzNfNv0oBVkVCmiyqQuVAbfRKajjoa7Js,378
@@ -209,12 +213,13 @@ airbyte_cdk/sources/file_based/config/file_based_stream_config.py,sha256=rkTuHpz
209
213
  airbyte_cdk/sources/file_based/config/jsonl_format.py,sha256=cxtpz4t9_ERQyj_1Bx4DjOxuYLykWt0B02S4dWW5BgM,378
210
214
  airbyte_cdk/sources/file_based/config/parquet_format.py,sha256=XOp-7nmm_WcbGI8SjKH2fs3Mkf1H4RAOYSWeUFYAz3w,741
211
215
  airbyte_cdk/sources/file_based/config/unstructured_format.py,sha256=tIbB9Pn1HqU67ju7hEZ9dBstRrb2eojUNMsdckzbj58,3565
216
+ airbyte_cdk/sources/file_based/config/validate_config_transfer_modes.py,sha256=OS52g6sJr98pKKLS4NO4ME3LCGy6qjjpWkHYWfG0Jtk,2925
212
217
  airbyte_cdk/sources/file_based/discovery_policy/__init__.py,sha256=gl3ey6mZbyfraB9P3pFhf9UJp2JeTZ1SUFAopy2iBvY,301
213
218
  airbyte_cdk/sources/file_based/discovery_policy/abstract_discovery_policy.py,sha256=dCfXX529Rd5rtopg4VeEgTPJjFtqjtjzPq6LCw18Wt0,605
214
219
  airbyte_cdk/sources/file_based/discovery_policy/default_discovery_policy.py,sha256=-xujTidtrq6HC00WKbjQh1CZdT5LMuzkp5BLjqDmfTY,1007
215
220
  airbyte_cdk/sources/file_based/exceptions.py,sha256=WP0qkG6fpWoBpOyyicgp5YNE393VWyegq5qSy0v4QtM,7362
216
- airbyte_cdk/sources/file_based/file_based_source.py,sha256=Biv2QufYQtHZQCBZs4iCUpqTd82rk7xo8SDYkEeau3k,17616
217
- airbyte_cdk/sources/file_based/file_based_stream_reader.py,sha256=e1KhgTh7mzvkBOz9DjLwzOsDwevrTmbxSYIcvhgWgGM,6856
221
+ airbyte_cdk/sources/file_based/file_based_source.py,sha256=JXfwc9KaW7PvjAbm2GJ7Ra3DJnCZH4KaE3WytYvtM1Q,18925
222
+ airbyte_cdk/sources/file_based/file_based_stream_reader.py,sha256=d2UZ3C8M-A591KvBvg8kDpVdpox0rKVlRhVy5bi-auc,11209
218
223
  airbyte_cdk/sources/file_based/file_types/__init__.py,sha256=blCLn0-2LC-ZdgcNyDEhqM2RiUvEjEBh-G4-t32ZtuM,1268
219
224
  airbyte_cdk/sources/file_based/file_types/avro_parser.py,sha256=XNx-JC-sgzH9u3nOJ2M59FxBXvtig8LN6BIkeDOavZA,10858
220
225
  airbyte_cdk/sources/file_based/file_types/csv_parser.py,sha256=QlCXB-ry3np67Q_VerQEPoWDOTcPTB6Go4ydZxY9ae4,20445
@@ -229,7 +234,7 @@ airbyte_cdk/sources/file_based/schema_helpers.py,sha256=Cf8FH1bDFP0qCDDfEYir_WjP
229
234
  airbyte_cdk/sources/file_based/schema_validation_policies/__init__.py,sha256=FkByIyEy56x2_awYnxGPqGaOp7zAzpAoRkPZHKySI9M,536
230
235
  airbyte_cdk/sources/file_based/schema_validation_policies/abstract_schema_validation_policy.py,sha256=kjvX7nOmUALYd7HuZHilUzgJPZ-MnZ08mtvuBnt2tQ0,618
231
236
  airbyte_cdk/sources/file_based/schema_validation_policies/default_schema_validation_policies.py,sha256=vjTlmYT_nqzY3DbT5xem7X-bwgA9RyXHoKFqiMO2URk,1728
232
- airbyte_cdk/sources/file_based/stream/__init__.py,sha256=QPDqdgjsabOQD93dSFqHGaFS_3pIwm-chEabZHiPJi0,265
237
+ airbyte_cdk/sources/file_based/stream/__init__.py,sha256=q_zmeOHHg0JK5j1YNSOIsyXGz-wlTl_0E8z5GKVAcVM,543
233
238
  airbyte_cdk/sources/file_based/stream/abstract_file_based_stream.py,sha256=9pQh3BHYcxm8CRC8XawfmBxL8O9HggpWwCCbX_ncINE,7509
234
239
  airbyte_cdk/sources/file_based/stream/concurrent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
235
240
  airbyte_cdk/sources/file_based/stream/concurrent/adapters.py,sha256=WZ5q2uovgohauJgwfxq_LFeZ92WMZd0LoH6c5QQURPo,13931
@@ -241,12 +246,15 @@ airbyte_cdk/sources/file_based/stream/cursor/__init__.py,sha256=MhFB5hOo8sjwvCh8
241
246
  airbyte_cdk/sources/file_based/stream/cursor/abstract_file_based_cursor.py,sha256=om-x3gZFPgWDpi15S9RxZmR36VHnk8sytgN6LlBQhAw,1934
242
247
  airbyte_cdk/sources/file_based/stream/cursor/default_file_based_cursor.py,sha256=VGV7xLyBribuBMVrXtO1xqkWJD86bl7yhXtjnwLMohM,7051
243
248
  airbyte_cdk/sources/file_based/stream/default_file_based_stream.py,sha256=XLU5cNqQ-5mj243gNzMyXtm_oCtg1ORyoqbCsUo9Dn4,18044
249
+ airbyte_cdk/sources/file_based/stream/identities_stream.py,sha256=DwgNU-jDp5vZ_WloQSUzBciDnAFMo8bXPjXpQx5-eko,1790
250
+ airbyte_cdk/sources/file_based/stream/permissions_file_based_stream.py,sha256=i0Jn0zuAPomLa4pHSu9TQ3gAN5xXhNzPTYVwUDiDEyE,3523
244
251
  airbyte_cdk/sources/file_based/types.py,sha256=INxG7OPnkdUP69oYNKMAbwhvV1AGvLRHs1J6pIia2FI,218
245
252
  airbyte_cdk/sources/http_config.py,sha256=OBZeuyFilm6NlDlBhFQvHhTWabEvZww6OHDIlZujIS0,730
246
253
  airbyte_cdk/sources/http_logger.py,sha256=l_1fk5YwdonZ1wvAsTwjj6d36fj2WrVraIAMj5jTQdM,1575
247
254
  airbyte_cdk/sources/message/__init__.py,sha256=y98fzHsQBwXwp2zEa4K5mxGFqjnx9lDn9O0pTk-VS4U,395
248
255
  airbyte_cdk/sources/message/repository.py,sha256=SG7avgti_-dj8FcRHTTrhgLLGJbElv14_zIB0SH8AIc,4763
249
256
  airbyte_cdk/sources/source.py,sha256=KIBBH5VLEb8BZ8B9aROlfaI6OLoJqKDPMJ10jkAR7nk,3611
257
+ airbyte_cdk/sources/specs/transfer_modes.py,sha256=sfSVO0yT6SaGKN5_TP0Nl_ftG0yPhecaBv0WkhAEXA8,932
250
258
  airbyte_cdk/sources/streams/__init__.py,sha256=8fzTKpRTnSx5PggXgQPKJzHNZUV2BCA40N-dI6JM1xI,256
251
259
  airbyte_cdk/sources/streams/availability_strategy.py,sha256=_RU4JITrxMEN36g1RDHMu0iSw0I_3yWGfo5N8_YRvOg,3247
252
260
  airbyte_cdk/sources/streams/call_rate.py,sha256=jRsGp1PDZBCDQNxzcGVnVmVzLk0wLHxS1JnJwMAgy9U,27568
@@ -299,6 +307,7 @@ airbyte_cdk/sources/streams/http/requests_native_auth/abstract_oauth.py,sha256=c
299
307
  airbyte_cdk/sources/streams/http/requests_native_auth/abstract_token.py,sha256=Y3n7J-sk5yGjv_OxtY6Z6k0PEsFZmtIRi-x0KCbaHdA,1010
300
308
  airbyte_cdk/sources/streams/http/requests_native_auth/oauth.py,sha256=C2j2uVfi9d-3KgHO3NGxIiFdfASjHOtsd6g_LWPYOAs,20311
301
309
  airbyte_cdk/sources/streams/http/requests_native_auth/token.py,sha256=h5PTzcdH-RQLeCg7xZ45w_484OPUDSwNWl_iMJQmZoI,2526
310
+ airbyte_cdk/sources/streams/permissions/identities_stream.py,sha256=9O9k6k18Xm3Zsiw_vnI_jsHXfMCQiek6V-jMkJJLxn8,2621
302
311
  airbyte_cdk/sources/streams/utils/__init__.py,sha256=4Hw-PX1-VgESLF16cDdvuYCzGJtHntThLF4qIiULWeo,61
303
312
  airbyte_cdk/sources/types.py,sha256=aFPGI4t2K1vHz2oFSUIYUyDN7kw-vcYq4D7aD2zgfAU,5128
304
313
  airbyte_cdk/sources/utils/__init__.py,sha256=TTN6VUxVy6Is8BhYQZR5pxJGQh8yH4duXh4O1TiMiEY,118
@@ -324,9 +333,9 @@ airbyte_cdk/test/catalog_builder.py,sha256=-y05Cz1x0Dlk6oE9LSKhCozssV2gYBNtMdV5Y
324
333
  airbyte_cdk/test/entrypoint_wrapper.py,sha256=9XBii_YguQp0d8cykn3hy102FsJcwIBQzSB7co5ho0s,9802
325
334
  airbyte_cdk/test/mock_http/__init__.py,sha256=jE5kC6CQ0OXkTqKhciDnNVZHesBFVIA2YvkdFGwva7k,322
326
335
  airbyte_cdk/test/mock_http/matcher.py,sha256=4Qj8UnJKZIs-eodshryce3SN1Ayc8GZpBETmP6hTEyc,1446
327
- airbyte_cdk/test/mock_http/mocker.py,sha256=HJjgFdapr7OALj0sfk-LVXYBiymbUDieaGa8U1_q730,7358
336
+ airbyte_cdk/test/mock_http/mocker.py,sha256=ghX44cLwhs7lqz1gYMizGX8zfPnDvt3YNI2w5jLpzIs,7726
328
337
  airbyte_cdk/test/mock_http/request.py,sha256=tdB8cqk2vLgCDTOKffBKsM06llYs4ZecgtH6DKyx6yY,4112
329
- airbyte_cdk/test/mock_http/response.py,sha256=U9KEsUkK2dPXYwnfwrwp6CcYSSpMYKLjfTrPFKSMCaM,602
338
+ airbyte_cdk/test/mock_http/response.py,sha256=s4-cQQqTtmeej0pQDWqmG0vUWpHS-93lIWMpW3zSVyU,662
330
339
  airbyte_cdk/test/mock_http/response_builder.py,sha256=debPx_lRYBaQVSwCoKLa0F8KFk3h0qG7bWxFBATa0cc,7958
331
340
  airbyte_cdk/test/state_builder.py,sha256=kLPql9lNzUJaBg5YYRLJlY_Hy5JLHJDVyKPMZMoYM44,946
332
341
  airbyte_cdk/test/utils/__init__.py,sha256=Hu-1XT2KDoYjDF7-_ziDwv5bY3PueGjANOCbzeOegDg,57
@@ -342,18 +351,18 @@ airbyte_cdk/utils/datetime_format_inferrer.py,sha256=Ne2cpk7Tx3eZDEW2Q3O7jnNOY9g
342
351
  airbyte_cdk/utils/datetime_helpers.py,sha256=8mqzZ67Or2PBp7tLtrhh6XFv4wFzYsjCL_DOQJRaftI,17751
343
352
  airbyte_cdk/utils/event_timing.py,sha256=aiuFmPU80buLlNdKq4fDTEqqhEIelHPF6AalFGwY8as,2557
344
353
  airbyte_cdk/utils/is_cloud_environment.py,sha256=DayV32Irh-SdnJ0MnjvstwCJ66_l5oEsd8l85rZtHoc,574
345
- airbyte_cdk/utils/mapping_helpers.py,sha256=4EOyUzNAGkq-M0QF5rPeBfT4v_eV7qBrEaAtsTH1k8Y,4309
354
+ airbyte_cdk/utils/mapping_helpers.py,sha256=imUTULHmZ1Ks-MRMRLIVqHCX1eJi_j6tFQrYsKIKtM4,5967
346
355
  airbyte_cdk/utils/message_utils.py,sha256=OTzbkwN7AdMDA3iKYq1LKwfPFxpyEDfdgEF9BED3dkU,1366
347
356
  airbyte_cdk/utils/oneof_option_config.py,sha256=N8EmWdYdwt0FM7fuShh6H8nj_r4KEL9tb2DJJtwsPow,1180
348
- airbyte_cdk/utils/print_buffer.py,sha256=0jhRBruCDPOwrytm03iVJp7C-2XPmaliMyENYJJEiac,2962
357
+ airbyte_cdk/utils/print_buffer.py,sha256=PhMOi0C4Z91kWKrSvCQXcp8qRh1uCimpIdvrg6voZIA,2810
349
358
  airbyte_cdk/utils/schema_inferrer.py,sha256=_jLzL9PzE4gfR44OSavkIqZNFM9t08c3LuRrkR7PZbk,9861
350
359
  airbyte_cdk/utils/slice_hasher.py,sha256=EDxgROHDbfG-QKQb59m7h_7crN1tRiawdf5uU7GrKcg,1264
351
360
  airbyte_cdk/utils/spec_schema_transformations.py,sha256=-5HTuNsnDBAhj-oLeQXwpTGA0HdcjFOf2zTEMUTTg_Y,816
352
361
  airbyte_cdk/utils/stream_status_utils.py,sha256=ZmBoiy5HVbUEHAMrUONxZvxnvfV9CesmQJLDTAIWnWw,1171
353
362
  airbyte_cdk/utils/traced_exception.py,sha256=C8uIBuCL_E4WnBAOPSxBicD06JAldoN9fGsQDp463OY,6292
354
- airbyte_cdk-6.34.0.dev0.dist-info/LICENSE.txt,sha256=Wfe61S4BaGPj404v8lrAbvhjYR68SHlkzeYrg3_bbuM,1051
355
- airbyte_cdk-6.34.0.dev0.dist-info/LICENSE_SHORT,sha256=aqF6D1NcESmpn-cqsxBtszTEnHKnlsp8L4x9wAh3Nxg,55
356
- airbyte_cdk-6.34.0.dev0.dist-info/METADATA,sha256=ru0Rv9rx2U3dGuLAtDmJoCJbgSqiIV2aVpGTYOxdUz0,6015
357
- airbyte_cdk-6.34.0.dev0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
358
- airbyte_cdk-6.34.0.dev0.dist-info/entry_points.txt,sha256=fj-e3PAQvsxsQzyyq8UkG1k8spunWnD4BAH2AwlR6NM,95
359
- airbyte_cdk-6.34.0.dev0.dist-info/RECORD,,
363
+ airbyte_cdk-6.34.0.dev2.dist-info/LICENSE.txt,sha256=Wfe61S4BaGPj404v8lrAbvhjYR68SHlkzeYrg3_bbuM,1051
364
+ airbyte_cdk-6.34.0.dev2.dist-info/LICENSE_SHORT,sha256=aqF6D1NcESmpn-cqsxBtszTEnHKnlsp8L4x9wAh3Nxg,55
365
+ airbyte_cdk-6.34.0.dev2.dist-info/METADATA,sha256=ocEC-CNtHU4hTlGp7U03ZuhKoyy4L2trucsaREiqru0,6015
366
+ airbyte_cdk-6.34.0.dev2.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
367
+ airbyte_cdk-6.34.0.dev2.dist-info/entry_points.txt,sha256=fj-e3PAQvsxsQzyyq8UkG1k8spunWnD4BAH2AwlR6NM,95
368
+ airbyte_cdk-6.34.0.dev2.dist-info/RECORD,,
@@ -1,448 +0,0 @@
1
- #
2
- # Copyright (c) 2023 Airbyte, Inc., all rights reserved.
3
- #
4
-
5
- import json
6
- import logging
7
- from copy import deepcopy
8
- from json import JSONDecodeError
9
- from typing import Any, Dict, Iterable, Iterator, List, Mapping, Optional, Union
10
-
11
- from airbyte_cdk.connector_builder.models import (
12
- AuxiliaryRequest,
13
- HttpRequest,
14
- HttpResponse,
15
- LogMessage,
16
- StreamRead,
17
- StreamReadPages,
18
- StreamReadSlices,
19
- )
20
- from airbyte_cdk.entrypoint import AirbyteEntrypoint
21
- from airbyte_cdk.models import (
22
- AirbyteControlMessage,
23
- AirbyteLogMessage,
24
- AirbyteMessage,
25
- AirbyteStateMessage,
26
- AirbyteTraceMessage,
27
- ConfiguredAirbyteCatalog,
28
- OrchestratorType,
29
- TraceType,
30
- )
31
- from airbyte_cdk.models import Type as MessageType
32
- from airbyte_cdk.sources.declarative.declarative_source import DeclarativeSource
33
- from airbyte_cdk.sources.utils.slice_logger import SliceLogger
34
- from airbyte_cdk.sources.utils.types import JsonType
35
- from airbyte_cdk.utils import AirbyteTracedException
36
- from airbyte_cdk.utils.datetime_format_inferrer import DatetimeFormatInferrer
37
- from airbyte_cdk.utils.schema_inferrer import SchemaInferrer, SchemaValidationException
38
-
39
-
40
- class MessageGrouper:
41
- logger = logging.getLogger("airbyte.connector-builder")
42
-
43
- def __init__(self, max_pages_per_slice: int, max_slices: int, max_record_limit: int = 1000):
44
- self._max_pages_per_slice = max_pages_per_slice
45
- self._max_slices = max_slices
46
- self._max_record_limit = max_record_limit
47
-
48
- def _pk_to_nested_and_composite_field(
49
- self, field: Optional[Union[str, List[str], List[List[str]]]]
50
- ) -> List[List[str]]:
51
- if not field:
52
- return [[]]
53
-
54
- if isinstance(field, str):
55
- return [[field]]
56
-
57
- is_composite_key = isinstance(field[0], str)
58
- if is_composite_key:
59
- return [[i] for i in field] # type: ignore # the type of field is expected to be List[str] here
60
-
61
- return field # type: ignore # the type of field is expected to be List[List[str]] here
62
-
63
- def _cursor_field_to_nested_and_composite_field(
64
- self, field: Union[str, List[str]]
65
- ) -> List[List[str]]:
66
- if not field:
67
- return [[]]
68
-
69
- if isinstance(field, str):
70
- return [[field]]
71
-
72
- is_nested_key = isinstance(field[0], str)
73
- if is_nested_key:
74
- return [field]
75
-
76
- raise ValueError(f"Unknown type for cursor field `{field}")
77
-
78
- def get_message_groups(
79
- self,
80
- source: DeclarativeSource,
81
- config: Mapping[str, Any],
82
- configured_catalog: ConfiguredAirbyteCatalog,
83
- state: List[AirbyteStateMessage],
84
- record_limit: Optional[int] = None,
85
- ) -> StreamRead:
86
- if record_limit is not None and not (1 <= record_limit <= self._max_record_limit):
87
- raise ValueError(
88
- f"Record limit must be between 1 and {self._max_record_limit}. Got {record_limit}"
89
- )
90
- stream = source.streams(config)[
91
- 0
92
- ] # The connector builder currently only supports reading from a single stream at a time
93
- schema_inferrer = SchemaInferrer(
94
- self._pk_to_nested_and_composite_field(stream.primary_key),
95
- self._cursor_field_to_nested_and_composite_field(stream.cursor_field),
96
- )
97
- datetime_format_inferrer = DatetimeFormatInferrer()
98
-
99
- if record_limit is None:
100
- record_limit = self._max_record_limit
101
- else:
102
- record_limit = min(record_limit, self._max_record_limit)
103
-
104
- slices = []
105
- log_messages = []
106
- latest_config_update: AirbyteControlMessage = None
107
- auxiliary_requests = []
108
- for message_group in self._get_message_groups(
109
- self._read_stream(source, config, configured_catalog, state),
110
- schema_inferrer,
111
- datetime_format_inferrer,
112
- record_limit,
113
- ):
114
- if isinstance(message_group, AirbyteLogMessage):
115
- log_messages.append(
116
- LogMessage(
117
- **{"message": message_group.message, "level": message_group.level.value}
118
- )
119
- )
120
- elif isinstance(message_group, AirbyteTraceMessage):
121
- if message_group.type == TraceType.ERROR:
122
- log_messages.append(
123
- LogMessage(
124
- **{
125
- "message": message_group.error.message,
126
- "level": "ERROR",
127
- "internal_message": message_group.error.internal_message,
128
- "stacktrace": message_group.error.stack_trace,
129
- }
130
- )
131
- )
132
- elif isinstance(message_group, AirbyteControlMessage):
133
- if (
134
- not latest_config_update
135
- or latest_config_update.emitted_at <= message_group.emitted_at
136
- ):
137
- latest_config_update = message_group
138
- elif isinstance(message_group, AuxiliaryRequest):
139
- auxiliary_requests.append(message_group)
140
- elif isinstance(message_group, StreamReadSlices):
141
- slices.append(message_group)
142
- else:
143
- raise ValueError(f"Unknown message group type: {type(message_group)}")
144
-
145
- try:
146
- # The connector builder currently only supports reading from a single stream at a time
147
- configured_stream = configured_catalog.streams[0]
148
- schema = schema_inferrer.get_stream_schema(configured_stream.stream.name)
149
- except SchemaValidationException as exception:
150
- for validation_error in exception.validation_errors:
151
- log_messages.append(LogMessage(validation_error, "ERROR"))
152
- schema = exception.schema
153
-
154
- return StreamRead(
155
- logs=log_messages,
156
- slices=slices,
157
- test_read_limit_reached=self._has_reached_limit(slices),
158
- auxiliary_requests=auxiliary_requests,
159
- inferred_schema=schema,
160
- latest_config_update=self._clean_config(latest_config_update.connectorConfig.config)
161
- if latest_config_update
162
- else None,
163
- inferred_datetime_formats=datetime_format_inferrer.get_inferred_datetime_formats(),
164
- )
165
-
166
- def _get_message_groups(
167
- self,
168
- messages: Iterator[AirbyteMessage],
169
- schema_inferrer: SchemaInferrer,
170
- datetime_format_inferrer: DatetimeFormatInferrer,
171
- limit: int,
172
- ) -> Iterable[
173
- Union[
174
- StreamReadPages,
175
- AirbyteControlMessage,
176
- AirbyteLogMessage,
177
- AirbyteTraceMessage,
178
- AuxiliaryRequest,
179
- ]
180
- ]:
181
- """
182
- Message groups are partitioned according to when request log messages are received. Subsequent response log messages
183
- and record messages belong to the prior request log message and when we encounter another request, append the latest
184
- message group, until <limit> records have been read.
185
-
186
- Messages received from the CDK read operation will always arrive in the following order:
187
- {type: LOG, log: {message: "request: ..."}}
188
- {type: LOG, log: {message: "response: ..."}}
189
- ... 0 or more record messages
190
- {type: RECORD, record: {data: ...}}
191
- {type: RECORD, record: {data: ...}}
192
- Repeats for each request/response made
193
-
194
- Note: The exception is that normal log messages can be received at any time which are not incorporated into grouping
195
- """
196
- records_count = 0
197
- at_least_one_page_in_group = False
198
- current_page_records: List[Mapping[str, Any]] = []
199
- current_slice_descriptor: Optional[Dict[str, Any]] = None
200
- current_slice_pages: List[StreamReadPages] = []
201
- current_page_request: Optional[HttpRequest] = None
202
- current_page_response: Optional[HttpResponse] = None
203
- latest_state_message: Optional[Dict[str, Any]] = None
204
-
205
- while records_count < limit and (message := next(messages, None)):
206
- json_object = self._parse_json(message.log) if message.type == MessageType.LOG else None
207
- if json_object is not None and not isinstance(json_object, dict):
208
- raise ValueError(
209
- f"Expected log message to be a dict, got {json_object} of type {type(json_object)}"
210
- )
211
- json_message: Optional[Dict[str, JsonType]] = json_object
212
- if self._need_to_close_page(at_least_one_page_in_group, message, json_message):
213
- self._close_page(
214
- current_page_request,
215
- current_page_response,
216
- current_slice_pages,
217
- current_page_records,
218
- )
219
- current_page_request = None
220
- current_page_response = None
221
-
222
- if (
223
- at_least_one_page_in_group
224
- and message.type == MessageType.LOG
225
- and message.log.message.startswith(SliceLogger.SLICE_LOG_PREFIX) # type: ignore[union-attr] # AirbyteMessage with MessageType.LOG has log.message
226
- ):
227
- yield StreamReadSlices(
228
- pages=current_slice_pages,
229
- slice_descriptor=current_slice_descriptor,
230
- state=[latest_state_message] if latest_state_message else [],
231
- )
232
- current_slice_descriptor = self._parse_slice_description(message.log.message) # type: ignore[union-attr] # AirbyteMessage with MessageType.LOG has log.message
233
- current_slice_pages = []
234
- at_least_one_page_in_group = False
235
- elif message.type == MessageType.LOG and message.log.message.startswith( # type: ignore[union-attr] # None doesn't have 'message'
236
- SliceLogger.SLICE_LOG_PREFIX
237
- ):
238
- # parsing the first slice
239
- current_slice_descriptor = self._parse_slice_description(message.log.message) # type: ignore[union-attr] # AirbyteMessage with MessageType.LOG has log.message
240
- elif message.type == MessageType.LOG:
241
- if json_message is not None and self._is_http_log(json_message):
242
- if self._is_auxiliary_http_request(json_message):
243
- airbyte_cdk = json_message.get("airbyte_cdk", {})
244
- if not isinstance(airbyte_cdk, dict):
245
- raise ValueError(
246
- f"Expected airbyte_cdk to be a dict, got {airbyte_cdk} of type {type(airbyte_cdk)}"
247
- )
248
- stream = airbyte_cdk.get("stream", {})
249
- if not isinstance(stream, dict):
250
- raise ValueError(
251
- f"Expected stream to be a dict, got {stream} of type {type(stream)}"
252
- )
253
- title_prefix = (
254
- "Parent stream: " if stream.get("is_substream", False) else ""
255
- )
256
- http = json_message.get("http", {})
257
- if not isinstance(http, dict):
258
- raise ValueError(
259
- f"Expected http to be a dict, got {http} of type {type(http)}"
260
- )
261
- yield AuxiliaryRequest(
262
- title=title_prefix + str(http.get("title", None)),
263
- description=str(http.get("description", None)),
264
- request=self._create_request_from_log_message(json_message),
265
- response=self._create_response_from_log_message(json_message),
266
- )
267
- else:
268
- at_least_one_page_in_group = True
269
- current_page_request = self._create_request_from_log_message(json_message)
270
- current_page_response = self._create_response_from_log_message(json_message)
271
- else:
272
- yield message.log
273
- elif message.type == MessageType.TRACE:
274
- if message.trace.type == TraceType.ERROR: # type: ignore[union-attr] # AirbyteMessage with MessageType.TRACE has trace.type
275
- yield message.trace
276
- elif message.type == MessageType.RECORD:
277
- current_page_records.append(message.record.data) # type: ignore[arg-type, union-attr] # AirbyteMessage with MessageType.RECORD has record.data
278
- records_count += 1
279
- schema_inferrer.accumulate(message.record)
280
- datetime_format_inferrer.accumulate(message.record)
281
- elif (
282
- message.type == MessageType.CONTROL
283
- and message.control.type == OrchestratorType.CONNECTOR_CONFIG # type: ignore[union-attr] # None doesn't have 'type'
284
- ):
285
- yield message.control
286
- elif message.type == MessageType.STATE:
287
- latest_state_message = message.state # type: ignore[assignment]
288
- else:
289
- if current_page_request or current_page_response or current_page_records:
290
- self._close_page(
291
- current_page_request,
292
- current_page_response,
293
- current_slice_pages,
294
- current_page_records,
295
- )
296
- yield StreamReadSlices(
297
- pages=current_slice_pages,
298
- slice_descriptor=current_slice_descriptor,
299
- state=[latest_state_message] if latest_state_message else [],
300
- )
301
-
302
- @staticmethod
303
- def _need_to_close_page(
304
- at_least_one_page_in_group: bool,
305
- message: AirbyteMessage,
306
- json_message: Optional[Dict[str, Any]],
307
- ) -> bool:
308
- return (
309
- at_least_one_page_in_group
310
- and message.type == MessageType.LOG
311
- and (
312
- MessageGrouper._is_page_http_request(json_message)
313
- or message.log.message.startswith("slice:") # type: ignore[union-attr] # AirbyteMessage with MessageType.LOG has log.message
314
- )
315
- )
316
-
317
- @staticmethod
318
- def _is_page_http_request(json_message: Optional[Dict[str, Any]]) -> bool:
319
- if not json_message:
320
- return False
321
- else:
322
- return MessageGrouper._is_http_log(
323
- json_message
324
- ) and not MessageGrouper._is_auxiliary_http_request(json_message)
325
-
326
- @staticmethod
327
- def _is_http_log(message: Dict[str, JsonType]) -> bool:
328
- return bool(message.get("http", False))
329
-
330
- @staticmethod
331
- def _is_auxiliary_http_request(message: Optional[Dict[str, Any]]) -> bool:
332
- """
333
- A auxiliary request is a request that is performed and will not directly lead to record for the specific stream it is being queried.
334
- A couple of examples are:
335
- * OAuth authentication
336
- * Substream slice generation
337
- """
338
- if not message:
339
- return False
340
-
341
- is_http = MessageGrouper._is_http_log(message)
342
- return is_http and message.get("http", {}).get("is_auxiliary", False)
343
-
344
- @staticmethod
345
- def _close_page(
346
- current_page_request: Optional[HttpRequest],
347
- current_page_response: Optional[HttpResponse],
348
- current_slice_pages: List[StreamReadPages],
349
- current_page_records: List[Mapping[str, Any]],
350
- ) -> None:
351
- """
352
- Close a page when parsing message groups
353
- """
354
- current_slice_pages.append(
355
- StreamReadPages(
356
- request=current_page_request,
357
- response=current_page_response,
358
- records=deepcopy(current_page_records), # type: ignore [arg-type]
359
- )
360
- )
361
- current_page_records.clear()
362
-
363
- def _read_stream(
364
- self,
365
- source: DeclarativeSource,
366
- config: Mapping[str, Any],
367
- configured_catalog: ConfiguredAirbyteCatalog,
368
- state: List[AirbyteStateMessage],
369
- ) -> Iterator[AirbyteMessage]:
370
- # the generator can raise an exception
371
- # iterate over the generated messages. if next raise an exception, catch it and yield it as an AirbyteLogMessage
372
- try:
373
- yield from AirbyteEntrypoint(source).read(
374
- source.spec(self.logger), config, configured_catalog, state
375
- )
376
- except AirbyteTracedException as traced_exception:
377
- # Look for this message which indicates that it is the "final exception" raised by AbstractSource.
378
- # If it matches, don't yield this as we don't need to show this in the Builder.
379
- # This is somewhat brittle as it relies on the message string, but if they drift then the worst case
380
- # is that this message will be shown in the Builder.
381
- if (
382
- traced_exception.message is not None
383
- and "During the sync, the following streams did not sync successfully"
384
- in traced_exception.message
385
- ):
386
- return
387
- yield traced_exception.as_airbyte_message()
388
- except Exception as e:
389
- error_message = f"{e.args[0] if len(e.args) > 0 else str(e)}"
390
- yield AirbyteTracedException.from_exception(
391
- e, message=error_message
392
- ).as_airbyte_message()
393
-
394
- @staticmethod
395
- def _parse_json(log_message: AirbyteLogMessage) -> JsonType:
396
- # TODO: As a temporary stopgap, the CDK emits request/response data as a log message string. Ideally this should come in the
397
- # form of a custom message object defined in the Airbyte protocol, but this unblocks us in the immediate while the
398
- # protocol change is worked on.
399
- try:
400
- json_object: JsonType = json.loads(log_message.message)
401
- return json_object
402
- except JSONDecodeError:
403
- return None
404
-
405
- @staticmethod
406
- def _create_request_from_log_message(json_http_message: Dict[str, Any]) -> HttpRequest:
407
- url = json_http_message.get("url", {}).get("full", "")
408
- request = json_http_message.get("http", {}).get("request", {})
409
- return HttpRequest(
410
- url=url,
411
- http_method=request.get("method", ""),
412
- headers=request.get("headers"),
413
- body=request.get("body", {}).get("content", ""),
414
- )
415
-
416
- @staticmethod
417
- def _create_response_from_log_message(json_http_message: Dict[str, Any]) -> HttpResponse:
418
- response = json_http_message.get("http", {}).get("response", {})
419
- body = response.get("body", {}).get("content", "")
420
- return HttpResponse(
421
- status=response.get("status_code"), body=body, headers=response.get("headers")
422
- )
423
-
424
- def _has_reached_limit(self, slices: List[StreamReadSlices]) -> bool:
425
- if len(slices) >= self._max_slices:
426
- return True
427
-
428
- record_count = 0
429
-
430
- for _slice in slices:
431
- if len(_slice.pages) >= self._max_pages_per_slice:
432
- return True
433
- for page in _slice.pages:
434
- record_count += len(page.records)
435
- if record_count >= self._max_record_limit:
436
- return True
437
- return False
438
-
439
- def _parse_slice_description(self, log_message: str) -> Dict[str, Any]:
440
- return json.loads(log_message.replace(SliceLogger.SLICE_LOG_PREFIX, "", 1)) # type: ignore
441
-
442
- @staticmethod
443
- def _clean_config(config: Dict[str, Any]) -> Dict[str, Any]:
444
- cleaned_config = deepcopy(config)
445
- for key in config.keys():
446
- if key.startswith("__"):
447
- del cleaned_config[key]
448
- return cleaned_config