dagster-airbyte 0.23.16__py3-none-any.whl → 0.24.1__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.

Potentially problematic release.


This version of dagster-airbyte might be problematic. Click here for more details.

@@ -0,0 +1 @@
1
+ partial
@@ -5,12 +5,14 @@ import sys
5
5
  import time
6
6
  from abc import abstractmethod
7
7
  from contextlib import contextmanager
8
+ from datetime import datetime, timedelta
8
9
  from typing import Any, Dict, List, Mapping, Optional, cast
9
10
 
10
11
  import requests
11
12
  from dagster import (
12
13
  ConfigurableResource,
13
14
  Failure,
15
+ InitResourceContext,
14
16
  _check as check,
15
17
  get_dagster_logger,
16
18
  resource,
@@ -19,13 +21,17 @@ from dagster._config.pythonic_config import infer_schema_from_config_class
19
21
  from dagster._core.definitions.resource_definition import dagster_maintained_resource
20
22
  from dagster._utils.cached_method import cached_method
21
23
  from dagster._utils.merger import deep_merge_dicts
22
- from pydantic import Field
24
+ from pydantic import Field, PrivateAttr
23
25
  from requests.exceptions import RequestException
24
26
 
25
27
  from dagster_airbyte.types import AirbyteOutput
26
28
 
27
29
  DEFAULT_POLL_INTERVAL_SECONDS = 10
28
30
 
31
+ # The access token expire every 3 minutes in Airbyte Cloud.
32
+ # Refresh is needed after 2.5 minutes to avoid the "token expired" error message.
33
+ AIRBYTE_CLOUD_REFRESH_TIMEDELTA_SECONDS = 150
34
+
29
35
 
30
36
  class AirbyteState:
31
37
  RUNNING = "running"
@@ -94,7 +100,11 @@ class BaseAirbyteResource(ConfigurableResource):
94
100
  raise NotImplementedError()
95
101
 
96
102
  def make_request(
97
- self, endpoint: str, data: Optional[Mapping[str, object]] = None, method: str = "POST"
103
+ self,
104
+ endpoint: str,
105
+ data: Optional[Mapping[str, object]] = None,
106
+ method: str = "POST",
107
+ include_additional_request_params: bool = True,
98
108
  ) -> Optional[Mapping[str, object]]:
99
109
  """Creates and sends a request to the desired Airbyte REST API endpoint.
100
110
 
@@ -120,10 +130,11 @@ class BaseAirbyteResource(ConfigurableResource):
120
130
  if data:
121
131
  request_args["json"] = data
122
132
 
123
- request_args = deep_merge_dicts(
124
- request_args,
125
- self.all_additional_request_params,
126
- )
133
+ if include_additional_request_params:
134
+ request_args = deep_merge_dicts(
135
+ request_args,
136
+ self.all_additional_request_params,
137
+ )
127
138
 
128
139
  response = requests.request(
129
140
  **request_args,
@@ -244,7 +255,7 @@ class BaseAirbyteResource(ConfigurableResource):
244
255
 
245
256
 
246
257
  class AirbyteCloudResource(BaseAirbyteResource):
247
- """This resource allows users to programatically interface with the Airbyte Cloud API to launch
258
+ """This resource allows users to programmatically interface with the Airbyte Cloud API to launch
248
259
  syncs and monitor their progress.
249
260
 
250
261
  **Examples:**
@@ -255,7 +266,8 @@ class AirbyteCloudResource(BaseAirbyteResource):
255
266
  from dagster_airbyte import AirbyteResource
256
267
 
257
268
  my_airbyte_resource = AirbyteCloudResource(
258
- api_key=EnvVar("AIRBYTE_API_KEY"),
269
+ client_id=EnvVar("AIRBYTE_CLIENT_ID"),
270
+ client_secret=EnvVar("AIRBYTE_CLIENT_SECRET"),
259
271
  )
260
272
 
261
273
  airbyte_assets = build_airbyte_assets(
@@ -269,7 +281,15 @@ class AirbyteCloudResource(BaseAirbyteResource):
269
281
  )
270
282
  """
271
283
 
272
- api_key: str = Field(..., description="The Airbyte Cloud API key.")
284
+ client_id: str = Field(..., description="The Airbyte Cloud client ID.")
285
+ client_secret: str = Field(..., description="The Airbyte Cloud client secret.")
286
+
287
+ _access_token_value: Optional[str] = PrivateAttr(default=None)
288
+ _access_token_timestamp: Optional[float] = PrivateAttr(default=None)
289
+
290
+ def setup_for_execution(self, context: InitResourceContext) -> None:
291
+ # Refresh access token when the resource is initialized
292
+ self._refresh_access_token()
273
293
 
274
294
  @property
275
295
  def api_base_url(self) -> str:
@@ -277,7 +297,32 @@ class AirbyteCloudResource(BaseAirbyteResource):
277
297
 
278
298
  @property
279
299
  def all_additional_request_params(self) -> Mapping[str, Any]:
280
- return {"headers": {"Authorization": f"Bearer {self.api_key}", "User-Agent": "dagster"}}
300
+ # Make sure the access token is refreshed before using it when calling the API.
301
+ if self._needs_refreshed_access_token():
302
+ self._refresh_access_token()
303
+ return {
304
+ "headers": {
305
+ "Authorization": f"Bearer {self._access_token_value}",
306
+ "User-Agent": "dagster",
307
+ }
308
+ }
309
+
310
+ def make_request(
311
+ self,
312
+ endpoint: str,
313
+ data: Optional[Mapping[str, object]] = None,
314
+ method: str = "POST",
315
+ include_additional_request_params: bool = True,
316
+ ) -> Optional[Mapping[str, object]]:
317
+ # Make sure the access token is refreshed before using it when calling the API.
318
+ if include_additional_request_params and self._needs_refreshed_access_token():
319
+ self._refresh_access_token()
320
+ return super().make_request(
321
+ endpoint=endpoint,
322
+ data=data,
323
+ method=method,
324
+ include_additional_request_params=include_additional_request_params,
325
+ )
281
326
 
282
327
  def start_sync(self, connection_id: str) -> Mapping[str, object]:
283
328
  job_sync = check.not_none(
@@ -306,6 +351,31 @@ class AirbyteCloudResource(BaseAirbyteResource):
306
351
  # Airbyte Cloud does not support streaming logs yet
307
352
  return False
308
353
 
354
+ def _refresh_access_token(self) -> None:
355
+ response = check.not_none(
356
+ self.make_request(
357
+ endpoint="/applications/token",
358
+ data={
359
+ "client_id": self.client_id,
360
+ "client_secret": self.client_secret,
361
+ },
362
+ # Must not pass the bearer access token when refreshing it.
363
+ include_additional_request_params=False,
364
+ )
365
+ )
366
+ self._access_token_value = str(response["access_token"])
367
+ self._access_token_timestamp = datetime.now().timestamp()
368
+
369
+ def _needs_refreshed_access_token(self) -> bool:
370
+ return (
371
+ not self._access_token_value
372
+ or not self._access_token_timestamp
373
+ or self._access_token_timestamp
374
+ <= datetime.timestamp(
375
+ datetime.now() - timedelta(seconds=AIRBYTE_CLOUD_REFRESH_TIMEDELTA_SECONDS)
376
+ )
377
+ )
378
+
309
379
 
310
380
  class AirbyteResource(BaseAirbyteResource):
311
381
  """This resource allows users to programatically interface with the Airbyte REST API to launch
@@ -1 +1 @@
1
- __version__ = "0.23.16"
1
+ __version__ = "0.24.1"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dagster-airbyte
3
- Version: 0.23.16
3
+ Version: 0.24.1
4
4
  Summary: Package for integrating Airbyte with Dagster.
5
5
  Home-page: https://github.com/dagster-io/dagster/tree/master/python_modules/libraries/dagster-airbyte
6
6
  Author: Dagster Labs
@@ -15,10 +15,10 @@ Classifier: License :: OSI Approved :: Apache Software License
15
15
  Classifier: Operating System :: OS Independent
16
16
  Requires-Python: >=3.8,<3.13
17
17
  License-File: LICENSE
18
- Requires-Dist: dagster ==1.7.16
18
+ Requires-Dist: dagster ==1.8.1
19
19
  Requires-Dist: requests
20
20
  Provides-Extra: managed
21
- Requires-Dist: dagster-managed-elements ==0.23.16 ; extra == 'managed'
21
+ Requires-Dist: dagster-managed-elements ==0.24.1 ; extra == 'managed'
22
22
  Provides-Extra: test
23
23
  Requires-Dist: requests-mock ; extra == 'test'
24
24
 
@@ -2,19 +2,20 @@ dagster_airbyte/__init__.py,sha256=KRUcHzOxDEmo9oO7qRwJNrRnxK28PeHTeUemMS4z2Gc,1
2
2
  dagster_airbyte/asset_defs.py,sha256=7PziNgIbN9xQwRjapygGvdWXI27p-ig6cdq6sRZ40W0,48511
3
3
  dagster_airbyte/cli.py,sha256=HErteP1MjfHozKKSrznh0yAreKETbXp5NDHzXGsdvvE,425
4
4
  dagster_airbyte/ops.py,sha256=fmZ7u223streZfx5Cwo0a-HhkWJVhBWiGsmwY9XXso8,4194
5
- dagster_airbyte/resources.py,sha256=ZRRKc1DwKluK6exEKkJ_FWIG5TKyTDOg1zt83TEM3Bg,27040
5
+ dagster_airbyte/py.typed,sha256=la67KBlbjXN-_-DfGNcdOcjYumVpKG_Tkw-8n5dnGB4,8
6
+ dagster_airbyte/resources.py,sha256=FoHI_Eiw2F6tnI1KZMfkgXhThdU6DplHp6INsbjUFsg,29802
6
7
  dagster_airbyte/types.py,sha256=fwqUv_MZCegwHhSELgUqm1H1JVUb-m83CyXFkd0r-ko,1425
7
8
  dagster_airbyte/utils.py,sha256=cFKCkGFAvwr17KFTeqpVtQRDsNo4zpqw9yr2-1YSJeI,2823
8
- dagster_airbyte/version.py,sha256=M0iweVcoG5aVc8DYn-pqd24UZQKlVsdhqQB4VFCL5Es,24
9
+ dagster_airbyte/version.py,sha256=23Q5wqrB_jTfEuw8bupXFhwqZO0_-oiISvjn1gCVUsA,23
9
10
  dagster_airbyte/managed/__init__.py,sha256=azuKhCI8eUsmEGBL2M2d6qkqQ0vhsV9H5IioP83kbm8,423
10
11
  dagster_airbyte/managed/reconciliation.py,sha256=HgrLT-Xs8vWY9SfbdBXuorMf60KCn5Qz7bPITW5MxJo,34862
11
12
  dagster_airbyte/managed/types.py,sha256=ja056Wm7_ZFw1XGSNmdxmBy2TcOxbnylJCpRA2ng2TE,14596
12
13
  dagster_airbyte/managed/generated/__init__.py,sha256=1ChWhXU1uyX_9rClMD6XHzkriKOc0fjIQntsoI3G99g,76
13
14
  dagster_airbyte/managed/generated/destinations.py,sha256=x1wmWlXvOJHtfaZva3ErdKuVS--sDvfidSXR5ji9G5w,119692
14
15
  dagster_airbyte/managed/generated/sources.py,sha256=e360ITeAECzqEvHw04onfBWciMntjR2IhoxOd5ibno4,282709
15
- dagster_airbyte-0.23.16.dist-info/LICENSE,sha256=TMatHW4_G9ldRdodEAp-l2Xa2WvsdeOh60E3v1R2jis,11349
16
- dagster_airbyte-0.23.16.dist-info/METADATA,sha256=xtbyfw3LT0aB-qENO_ioqaQxabpMOi1ZJPiV2As-Pdg,929
17
- dagster_airbyte-0.23.16.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
18
- dagster_airbyte-0.23.16.dist-info/entry_points.txt,sha256=XrbLOz3LpgPV5fdwMmgdP6Rp1AfSG07KeWIddLqh7Lw,61
19
- dagster_airbyte-0.23.16.dist-info/top_level.txt,sha256=HLwIRQCzqItn88_KbPP8DNTKKQEBUVKk6NCn4PrCtqY,16
20
- dagster_airbyte-0.23.16.dist-info/RECORD,,
16
+ dagster_airbyte-0.24.1.dist-info/LICENSE,sha256=TMatHW4_G9ldRdodEAp-l2Xa2WvsdeOh60E3v1R2jis,11349
17
+ dagster_airbyte-0.24.1.dist-info/METADATA,sha256=B7cPCw8Oeh20-PnZq8RdbbxbdUodGAOtmh4JdBRqbIM,926
18
+ dagster_airbyte-0.24.1.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
19
+ dagster_airbyte-0.24.1.dist-info/entry_points.txt,sha256=XrbLOz3LpgPV5fdwMmgdP6Rp1AfSG07KeWIddLqh7Lw,61
20
+ dagster_airbyte-0.24.1.dist-info/top_level.txt,sha256=HLwIRQCzqItn88_KbPP8DNTKKQEBUVKk6NCn4PrCtqY,16
21
+ dagster_airbyte-0.24.1.dist-info/RECORD,,