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.
- airbyte_cdk/connector_builder/connector_builder_handler.py +16 -12
- airbyte_cdk/connector_builder/test_reader/__init__.py +7 -0
- airbyte_cdk/connector_builder/test_reader/helpers.py +591 -0
- airbyte_cdk/connector_builder/test_reader/message_grouper.py +160 -0
- airbyte_cdk/connector_builder/test_reader/reader.py +441 -0
- airbyte_cdk/connector_builder/test_reader/types.py +75 -0
- airbyte_cdk/entrypoint.py +6 -6
- airbyte_cdk/logger.py +1 -4
- airbyte_cdk/sources/declarative/incremental/concurrent_partition_cursor.py +122 -38
- airbyte_cdk/sources/declarative/incremental/datetime_based_cursor.py +5 -0
- airbyte_cdk/sources/declarative/requesters/paginators/default_paginator.py +10 -0
- airbyte_cdk/sources/file_based/config/abstract_file_based_spec.py +2 -1
- airbyte_cdk/sources/file_based/config/validate_config_transfer_modes.py +81 -0
- airbyte_cdk/sources/file_based/file_based_source.py +70 -37
- airbyte_cdk/sources/file_based/file_based_stream_reader.py +107 -12
- airbyte_cdk/sources/file_based/stream/__init__.py +10 -1
- airbyte_cdk/sources/file_based/stream/identities_stream.py +47 -0
- airbyte_cdk/sources/file_based/stream/permissions_file_based_stream.py +85 -0
- airbyte_cdk/sources/specs/transfer_modes.py +26 -0
- airbyte_cdk/sources/streams/permissions/identities_stream.py +75 -0
- airbyte_cdk/test/mock_http/mocker.py +9 -1
- airbyte_cdk/test/mock_http/response.py +6 -3
- airbyte_cdk/utils/mapping_helpers.py +43 -2
- airbyte_cdk/utils/print_buffer.py +0 -4
- {airbyte_cdk-6.34.0.dev0.dist-info → airbyte_cdk-6.34.0.dev2.dist-info}/METADATA +1 -1
- {airbyte_cdk-6.34.0.dev0.dist-info → airbyte_cdk-6.34.0.dev2.dist-info}/RECORD +30 -21
- airbyte_cdk/connector_builder/message_grouper.py +0 -448
- {airbyte_cdk-6.34.0.dev0.dist-info → airbyte_cdk-6.34.0.dev2.dist-info}/LICENSE.txt +0 -0
- {airbyte_cdk-6.34.0.dev0.dist-info → airbyte_cdk-6.34.0.dev2.dist-info}/LICENSE_SHORT +0 -0
- {airbyte_cdk-6.34.0.dev0.dist-info → airbyte_cdk-6.34.0.dev2.dist-info}/WHEEL +0 -0
- {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=
|
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=
|
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=
|
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=
|
92
|
-
airbyte_cdk/sources/declarative/incremental/datetime_based_cursor.py,sha256=
|
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=
|
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=
|
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=
|
217
|
-
airbyte_cdk/sources/file_based/file_based_stream_reader.py,sha256=
|
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=
|
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=
|
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=
|
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=
|
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=
|
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.
|
355
|
-
airbyte_cdk-6.34.0.
|
356
|
-
airbyte_cdk-6.34.0.
|
357
|
-
airbyte_cdk-6.34.0.
|
358
|
-
airbyte_cdk-6.34.0.
|
359
|
-
airbyte_cdk-6.34.0.
|
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
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|