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

@@ -1,36 +1,41 @@
1
- from collections.abc import Sequence
1
+ from collections import defaultdict
2
+ from collections.abc import Iterable, Sequence
2
3
  from functools import cached_property
4
+ from pathlib import Path
3
5
  from typing import Annotated, Callable, Optional, Union
4
6
 
5
7
  import dagster as dg
6
8
  import pydantic
7
9
  from dagster._annotations import superseded
8
- from dagster._core.definitions.job_definition import default_job_io_manager
10
+ from dagster._utils.names import clean_name
11
+ from dagster.components.component.state_backed_component import StateBackedComponent
9
12
  from dagster.components.resolved.base import resolve_fields
10
- from dagster.components.utils.translation import TranslationFn, TranslationFnResolver
13
+ from dagster.components.utils.defs_state import (
14
+ DefsStateConfig,
15
+ DefsStateConfigArgs,
16
+ ResolvedDefsStateConfig,
17
+ )
18
+ from dagster.components.utils.translation import (
19
+ ComponentTranslator,
20
+ TranslationFn,
21
+ TranslationFnResolver,
22
+ create_component_translator_cls,
23
+ )
11
24
  from dagster_shared import check
25
+ from dagster_shared.serdes.serdes import deserialize_value
12
26
 
13
- from dagster_airbyte.asset_defs import build_airbyte_assets_definitions
14
27
  from dagster_airbyte.components.workspace_component.scaffolder import (
15
28
  AirbyteWorkspaceComponentScaffolder,
16
29
  )
17
- from dagster_airbyte.resources import AirbyteCloudWorkspace, AirbyteWorkspace
30
+ from dagster_airbyte.resources import AirbyteCloudWorkspace, AirbyteWorkspace, BaseAirbyteWorkspace
18
31
  from dagster_airbyte.translator import (
19
32
  AirbyteConnection,
20
33
  AirbyteConnectionTableProps,
34
+ AirbyteMetadataSet,
35
+ AirbyteWorkspaceData,
21
36
  DagsterAirbyteTranslator,
22
37
  )
23
-
24
-
25
- class ProxyDagsterAirbyteTranslator(DagsterAirbyteTranslator):
26
- def __init__(self, fn: TranslationFn[AirbyteConnectionTableProps]):
27
- self.fn = fn
28
-
29
- def get_asset_spec(self, props: AirbyteConnectionTableProps) -> dg.AssetSpec:
30
- base_asset_spec = super().get_asset_spec(props)
31
- spec = self.fn(base_asset_spec, props)
32
-
33
- return spec
38
+ from dagster_airbyte.utils import DAGSTER_AIRBYTE_TRANSLATOR_METADATA_KEY
34
39
 
35
40
 
36
41
  class BaseAirbyteWorkspaceModel(dg.Model, dg.Resolvable):
@@ -168,7 +173,7 @@ def resolve_airbyte_workspace_type(context: dg.ResolutionContext, model):
168
173
 
169
174
 
170
175
  @dg.scaffold_with(AirbyteWorkspaceComponentScaffolder)
171
- class AirbyteWorkspaceComponent(dg.Component, dg.Model, dg.Resolvable):
176
+ class AirbyteWorkspaceComponent(StateBackedComponent, dg.Model, dg.Resolvable):
172
177
  """Loads Airbyte connections from a given Airbyte workspace as Dagster assets.
173
178
  Materializing these assets will trigger a sync of the Airbyte connection, enabling
174
179
  you to schedule Airbyte syncs using Dagster.
@@ -197,34 +202,97 @@ class AirbyteWorkspaceComponent(dg.Component, dg.Model, dg.Resolvable):
197
202
  TranslationFnResolver(template_vars_for_translation_fn=lambda data: {"props": data}),
198
203
  ]
199
204
  ] = pydantic.Field(
200
- None,
205
+ default=None,
201
206
  description="Function used to translate Airbyte connection table properties into Dagster asset specs.",
202
207
  )
208
+ defs_state: ResolvedDefsStateConfig = DefsStateConfigArgs.legacy_code_server_snapshots()
209
+
210
+ @property
211
+ def defs_state_config(self) -> DefsStateConfig:
212
+ default_key = f"{self.__class__.__name__}[{self.workspace.workspace_id}]"
213
+ return DefsStateConfig.from_args(self.defs_state, default_key=default_key)
203
214
 
204
215
  @cached_property
205
216
  def translator(self) -> DagsterAirbyteTranslator:
206
- if self.translation:
207
- return ProxyDagsterAirbyteTranslator(self.translation)
217
+ return AirbyteComponentTranslator(self)
218
+
219
+ @cached_property
220
+ def _base_translator(self) -> DagsterAirbyteTranslator:
208
221
  return DagsterAirbyteTranslator()
209
222
 
210
- def build_defs(self, context: dg.ComponentLoadContext) -> dg.Definitions:
211
- airbyte_assets = build_airbyte_assets_definitions(
212
- workspace=self.workspace,
213
- dagster_airbyte_translator=self.translator,
214
- connection_selector_fn=self.connection_selector,
223
+ def get_asset_spec(self, props: AirbyteConnectionTableProps) -> dg.AssetSpec:
224
+ return self._base_translator.get_asset_spec(props)
225
+
226
+ def execute(
227
+ self, context: dg.AssetExecutionContext, airbyte: BaseAirbyteWorkspace
228
+ ) -> Iterable[Union[dg.AssetMaterialization, dg.MaterializeResult]]:
229
+ yield from airbyte.sync_and_poll(context=context)
230
+
231
+ def _load_asset_specs(self, state: AirbyteWorkspaceData) -> Sequence[dg.AssetSpec]:
232
+ connection_selector_fn = self.connection_selector or (lambda connection: True)
233
+ return [
234
+ self.translator.get_asset_spec(props).merge_attributes(
235
+ metadata={DAGSTER_AIRBYTE_TRANSLATOR_METADATA_KEY: self.translator}
236
+ )
237
+ for props in state.to_airbyte_connection_table_props_data()
238
+ if connection_selector_fn(state.connections_by_id[props.connection_id])
239
+ ]
240
+
241
+ def _get_airbyte_assets_def(
242
+ self, connection_name: str, specs: Sequence[dg.AssetSpec]
243
+ ) -> dg.AssetsDefinition:
244
+ @dg.multi_asset(
245
+ name=f"airbyte_{clean_name(connection_name)}",
246
+ can_subset=True,
247
+ specs=specs,
215
248
  )
216
- assets_with_resource = [
217
- airbyte_asset.with_resources(
218
- {
219
- "airbyte": self.workspace.get_resource_definition(),
220
- "io_manager": default_job_io_manager,
221
- }
249
+ def _asset(context: dg.AssetExecutionContext):
250
+ yield from self.execute(context=context, airbyte=self.workspace)
251
+
252
+ return _asset
253
+
254
+ async def write_state_to_path(self, state_path: Path) -> None:
255
+ state = self.workspace.fetch_airbyte_workspace_data()
256
+ state_path.write_text(dg.serialize_value(state))
257
+
258
+ def build_defs_from_state(
259
+ self, context: dg.ComponentLoadContext, state_path: Optional[Path]
260
+ ) -> dg.Definitions:
261
+ if state_path is None:
262
+ return dg.Definitions()
263
+ state = deserialize_value(state_path.read_text(), AirbyteWorkspaceData)
264
+
265
+ # group specs by their connector names
266
+ specs_by_connection_name = defaultdict(list)
267
+ for spec in self._load_asset_specs(state):
268
+ connection_name = check.not_none(
269
+ AirbyteMetadataSet.extract(spec.metadata).connection_name
222
270
  )
223
- for airbyte_asset in airbyte_assets
271
+ specs_by_connection_name[connection_name].append(spec)
272
+
273
+ # create one assets definition per connection
274
+ assets = [
275
+ self._get_airbyte_assets_def(connection_name, specs)
276
+ for connection_name, specs in specs_by_connection_name.items()
224
277
  ]
225
- return dg.Definitions(assets=assets_with_resource)
278
+ return dg.Definitions(assets=assets)
226
279
 
227
280
 
228
281
  # Subclassing to create the alias to be able to use the superseded decorator.
229
282
  @superseded(additional_warn_text="Superseded. Use AirbyteWorkspaceComponent instead.")
230
283
  class AirbyteCloudWorkspaceComponent(AirbyteWorkspaceComponent): ...
284
+
285
+
286
+ class AirbyteComponentTranslator(
287
+ create_component_translator_cls(AirbyteWorkspaceComponent, DagsterAirbyteTranslator),
288
+ ComponentTranslator[AirbyteWorkspaceComponent],
289
+ ):
290
+ def __init__(self, component: AirbyteWorkspaceComponent):
291
+ self._component = component
292
+
293
+ def get_asset_spec(self, props: AirbyteConnectionTableProps) -> dg.AssetSpec:
294
+ base_asset_spec = super().get_asset_spec(props)
295
+ if self.component.translation is None:
296
+ return base_asset_spec
297
+ else:
298
+ return self.component.translation(base_asset_spec, props)
@@ -1 +1 @@
1
- __version__ = "0.27.13"
1
+ __version__ = "0.27.15"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dagster-airbyte
3
- Version: 0.27.13
3
+ Version: 0.27.15
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,13 +15,13 @@ Classifier: License :: OSI Approved :: Apache Software License
15
15
  Classifier: Operating System :: OS Independent
16
16
  Requires-Python: >=3.9,<3.14
17
17
  License-File: LICENSE
18
- Requires-Dist: dagster==1.11.13
18
+ Requires-Dist: dagster==1.11.15
19
19
  Requires-Dist: requests
20
20
  Provides-Extra: test
21
21
  Requires-Dist: requests-mock; extra == "test"
22
22
  Requires-Dist: flaky; extra == "test"
23
23
  Provides-Extra: managed
24
- Requires-Dist: dagster-managed-elements==0.27.13; extra == "managed"
24
+ Requires-Dist: dagster-managed-elements==0.27.15; extra == "managed"
25
25
  Dynamic: author
26
26
  Dynamic: author-email
27
27
  Dynamic: classifier
@@ -8,10 +8,10 @@ dagster_airbyte/resources.py,sha256=AXN_mtNl_JKauoOY29wyuiv9jjAiCNF9M4baVCQPMYo,
8
8
  dagster_airbyte/translator.py,sha256=RY2LhGPACIfyd2zOSH1swdLz4koX6_bvclW-alS3Bic,7547
9
9
  dagster_airbyte/types.py,sha256=TYUjI3skjLYeANjesgJ-IAJNu8bAnL1ymsUfz5LsRTE,1565
10
10
  dagster_airbyte/utils.py,sha256=wG9119kXi87JgcOjK7iNozr-svZocJBQYoHBMmnXZcE,4092
11
- dagster_airbyte/version.py,sha256=rEMnLvYM5w34kWC8YIc4QXFgiezRHgYr2j_AJji8ui8,24
11
+ dagster_airbyte/version.py,sha256=nh4rkWKwcS4_2NEvEKWozrztgCUEn_1ODIolwNpGd8g,24
12
12
  dagster_airbyte/components/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
13
  dagster_airbyte/components/workspace_component/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
- dagster_airbyte/components/workspace_component/component.py,sha256=TIl8Ja6BHwpyRmkzkn-o75sH1dOUbbHtTftAb68Ag_c,8445
14
+ dagster_airbyte/components/workspace_component/component.py,sha256=nGOQXivXS-Zc69_K1aq2xATT06Roci3fAJ-5x1xOqgU,11238
15
15
  dagster_airbyte/components/workspace_component/scaffolder.py,sha256=zk5HDJ6C8zcfUWKslJVyqyBB0LV3JzNAocY2ptT517s,1046
16
16
  dagster_airbyte/managed/__init__.py,sha256=6SBtyNOMJ9Cu2UIwFExJHpL_ZVFo3rPMvyIxVOsKvWE,469
17
17
  dagster_airbyte/managed/reconciliation.py,sha256=xoVfqPBpNSldkiqOLIPnc7ei8CppHKWtzv8bvxjdqlI,34859
@@ -19,9 +19,9 @@ dagster_airbyte/managed/types.py,sha256=isPfX8L9YwtZAf9Vk4hhxBePLR00AEldsdK2TsM1
19
19
  dagster_airbyte/managed/generated/__init__.py,sha256=eYq-yfXEeffuKAVFXY8plD0se1wHjFNVqklpbu9gljw,108
20
20
  dagster_airbyte/managed/generated/destinations.py,sha256=x1wmWlXvOJHtfaZva3ErdKuVS--sDvfidSXR5ji9G5w,119692
21
21
  dagster_airbyte/managed/generated/sources.py,sha256=y0TPNvcRd8c9mhje-NoXsHeKRPt1nXcpww8mNAtqCps,282685
22
- dagster_airbyte-0.27.13.dist-info/licenses/LICENSE,sha256=4lsMW-RCvfVD4_F57wrmpe3vX1xwUk_OAKKmV_XT7Z0,11348
23
- dagster_airbyte-0.27.13.dist-info/METADATA,sha256=WWUOmQj-uKukv-8S2boTU0nKxUIdLi-l_zinaNRkOyw,1169
24
- dagster_airbyte-0.27.13.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
25
- dagster_airbyte-0.27.13.dist-info/entry_points.txt,sha256=096yvfMP-gNsCgDg9vDQtinis5QGpD-e_kHEhcHaML8,120
26
- dagster_airbyte-0.27.13.dist-info/top_level.txt,sha256=HLwIRQCzqItn88_KbPP8DNTKKQEBUVKk6NCn4PrCtqY,16
27
- dagster_airbyte-0.27.13.dist-info/RECORD,,
22
+ dagster_airbyte-0.27.15.dist-info/licenses/LICENSE,sha256=4lsMW-RCvfVD4_F57wrmpe3vX1xwUk_OAKKmV_XT7Z0,11348
23
+ dagster_airbyte-0.27.15.dist-info/METADATA,sha256=lvl1x_vvakCJSW40mnHZe-kahcduGWPQZzjMYQ2CObk,1169
24
+ dagster_airbyte-0.27.15.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
25
+ dagster_airbyte-0.27.15.dist-info/entry_points.txt,sha256=096yvfMP-gNsCgDg9vDQtinis5QGpD-e_kHEhcHaML8,120
26
+ dagster_airbyte-0.27.15.dist-info/top_level.txt,sha256=HLwIRQCzqItn88_KbPP8DNTKKQEBUVKk6NCn4PrCtqY,16
27
+ dagster_airbyte-0.27.15.dist-info/RECORD,,