altimate-datapilot-cli 0.0.13__py3-none-any.whl → 0.0.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.
Files changed (32) hide show
  1. {altimate_datapilot_cli-0.0.13.dist-info → altimate_datapilot_cli-0.0.15.dist-info}/METADATA +7 -6
  2. {altimate_datapilot_cli-0.0.13.dist-info → altimate_datapilot_cli-0.0.15.dist-info}/RECORD +32 -28
  3. {altimate_datapilot_cli-0.0.13.dist-info → altimate_datapilot_cli-0.0.15.dist-info}/WHEEL +1 -1
  4. datapilot/__init__.py +1 -1
  5. datapilot/clients/altimate/client.py +18 -1
  6. datapilot/clients/altimate/utils.py +30 -0
  7. datapilot/constants.py +7 -0
  8. datapilot/core/insights/sql/base/insight.py +2 -9
  9. datapilot/core/platforms/dbt/cli/cli.py +21 -2
  10. datapilot/core/platforms/dbt/constants.py +2 -0
  11. datapilot/core/platforms/dbt/executor.py +69 -0
  12. datapilot/core/platforms/dbt/insights/__init__.py +2 -0
  13. datapilot/core/platforms/dbt/insights/base.py +3 -0
  14. datapilot/core/platforms/dbt/insights/checks/check_model_has_labels_keys.py +1 -1
  15. datapilot/core/platforms/dbt/insights/checks/check_model_has_meta_keys.py +1 -1
  16. datapilot/core/platforms/dbt/insights/checks/check_source_has_freshness.py +1 -1
  17. datapilot/core/platforms/dbt/insights/checks/check_source_has_labels_keys.py +1 -1
  18. datapilot/core/platforms/dbt/insights/checks/check_source_has_meta_keys.py +1 -1
  19. datapilot/core/platforms/dbt/insights/sql/__init__.py +0 -0
  20. datapilot/core/platforms/dbt/insights/sql/base.py +23 -0
  21. datapilot/core/platforms/dbt/insights/sql/sql_check.py +101 -0
  22. datapilot/core/platforms/dbt/schemas/catalog.py +21 -13
  23. datapilot/core/platforms/dbt/schemas/manifest.py +41 -27
  24. datapilot/core/platforms/dbt/wrappers/manifest/v10/wrapper.py +82 -64
  25. datapilot/core/platforms/dbt/wrappers/manifest/v11/wrapper.py +93 -75
  26. datapilot/core/platforms/dbt/wrappers/manifest/v12/schemas.py +13 -13
  27. datapilot/core/platforms/dbt/wrappers/manifest/v12/wrapper.py +25 -19
  28. datapilot/core/platforms/dbt/wrappers/manifest/wrapper.py +5 -0
  29. {altimate_datapilot_cli-0.0.13.dist-info → altimate_datapilot_cli-0.0.15.dist-info}/AUTHORS.rst +0 -0
  30. {altimate_datapilot_cli-0.0.13.dist-info → altimate_datapilot_cli-0.0.15.dist-info}/LICENSE +0 -0
  31. {altimate_datapilot_cli-0.0.13.dist-info → altimate_datapilot_cli-0.0.15.dist-info}/entry_points.txt +0 -0
  32. {altimate_datapilot_cli-0.0.13.dist-info → altimate_datapilot_cli-0.0.15.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,101 @@
1
+ import inspect
2
+ from typing import List
3
+
4
+ from sqlglot import parse_one
5
+ from sqlglot.optimizer.eliminate_ctes import eliminate_ctes
6
+ from sqlglot.optimizer.eliminate_joins import eliminate_joins
7
+ from sqlglot.optimizer.eliminate_subqueries import eliminate_subqueries
8
+ from sqlglot.optimizer.normalize import normalize
9
+ from sqlglot.optimizer.pushdown_projections import pushdown_projections
10
+ from sqlglot.optimizer.qualify import qualify
11
+ from sqlglot.optimizer.unnest_subqueries import unnest_subqueries
12
+
13
+ from datapilot.core.insights.sql.base.insight import SqlInsight
14
+ from datapilot.core.insights.utils import get_severity
15
+ from datapilot.core.platforms.dbt.insights.schema import DBTInsightResult
16
+ from datapilot.core.platforms.dbt.insights.schema import DBTModelInsightResponse
17
+
18
+ RULES = (
19
+ pushdown_projections,
20
+ normalize,
21
+ unnest_subqueries,
22
+ eliminate_subqueries,
23
+ eliminate_joins,
24
+ eliminate_ctes,
25
+ )
26
+
27
+
28
+ class SqlCheck(SqlInsight):
29
+ """
30
+ This class identifies DBT models with SQL optimization issues.
31
+ """
32
+
33
+ NAME = "sql optimization issues"
34
+ ALIAS = "check_sql_optimization"
35
+ DESCRIPTION = "Checks if the model has SQL optimization issues. "
36
+ REASON_TO_FLAG = "The query can be optimized."
37
+ FAILURE_MESSAGE = "The query for model `{model_unique_id}` has optimization opportunities:\n{rule_name}. "
38
+ RECOMMENDATION = "Please adapt the query of the model `{model_unique_id}` as in following example:\n{optimized_sql}"
39
+
40
+ def _build_failure_result(self, model_unique_id: str, rule_name: str, optimized_sql: str) -> DBTInsightResult:
41
+ """
42
+ Constructs a failure result for a given model with sql optimization issues.
43
+ :param model_unique_id: The unique id of the dbt model.
44
+ :param rule_name: The rule that generated this failure result.
45
+ :param optimized_sql: The optimized sql.
46
+ :return: An instance of DBTInsightResult containing failure details.
47
+ """
48
+ failure_message = self.FAILURE_MESSAGE.format(model_unique_id=model_unique_id, rule_name=rule_name)
49
+ recommendation = self.RECOMMENDATION.format(model_unique_id=model_unique_id, optimized_sql=optimized_sql)
50
+ return DBTInsightResult(
51
+ type=self.TYPE,
52
+ name=self.NAME,
53
+ message=failure_message,
54
+ recommendation=recommendation,
55
+ reason_to_flag=self.REASON_TO_FLAG,
56
+ metadata={"model_unique_id": model_unique_id, "rule_name": rule_name},
57
+ )
58
+
59
+ def generate(self, *args, **kwargs) -> List[DBTModelInsightResponse]:
60
+ """
61
+ Generates insights for each DBT model in the project, focusing on sql optimization issues.
62
+
63
+ :return: A list of DBTModelInsightResponse objects with insights for each model.
64
+ """
65
+ self.logger.debug("Generating sql insights for DBT models")
66
+ insights = []
67
+
68
+ possible_kwargs = {
69
+ "db": None,
70
+ "catalog": None,
71
+ "dialect": self.adapter_type,
72
+ "isolate_tables": True, # needed for other optimizations to perform well
73
+ "quote_identifiers": False,
74
+ **kwargs,
75
+ }
76
+ for node_id, node in self.nodes.items():
77
+ try:
78
+ compiled_query = node.compiled_code
79
+ if compiled_query:
80
+ parsed_query = parse_one(compiled_query, dialect=self.adapter_type)
81
+ qualified = qualify(parsed_query, **possible_kwargs)
82
+ changed = qualified.copy()
83
+ for rule in RULES:
84
+ original = changed.copy()
85
+ rule_params = inspect.getfullargspec(rule).args
86
+ rule_kwargs = {param: possible_kwargs[param] for param in rule_params if param in possible_kwargs}
87
+ changed = rule(changed, **rule_kwargs)
88
+ if changed.sql() != original.sql():
89
+ insights.append(
90
+ DBTModelInsightResponse(
91
+ unique_id=node_id,
92
+ package_name=node.package_name,
93
+ path=node.original_file_path,
94
+ original_file_path=node.original_file_path,
95
+ insight=self._build_failure_result(node_id, rule.__name__, changed.sql()),
96
+ severity=get_severity(self.config, self.ALIAS, self.DEFAULT_SEVERITY),
97
+ )
98
+ )
99
+ except Exception as e:
100
+ self.logger.error(e)
101
+ return insights
@@ -5,13 +5,16 @@ from typing import List
5
5
  from typing import Optional
6
6
  from typing import Union
7
7
 
8
- from pydantic.config import Extra
8
+ from pydantic import ConfigDict
9
9
  from pydantic.main import BaseModel
10
10
 
11
+ from datapilot.constants import Extra
12
+
11
13
 
12
14
  class AltimateCatalogMetadata(BaseModel):
13
- class Config:
14
- extra = Extra.forbid
15
+ model_config = ConfigDict(
16
+ extra=Extra.forbid,
17
+ )
15
18
 
16
19
  dbt_schema_version: Optional[str] = "https://schemas.getdbt.com/dbt/catalog/v1.json"
17
20
  dbt_version: Optional[str] = "0.19.0"
@@ -21,8 +24,9 @@ class AltimateCatalogMetadata(BaseModel):
21
24
 
22
25
 
23
26
  class AltimateCatalogTableMetadata(BaseModel):
24
- class Config:
25
- extra = Extra.forbid
27
+ model_config = ConfigDict(
28
+ extra=Extra.forbid,
29
+ )
26
30
 
27
31
  type: str
28
32
  database: Optional[Optional[str]] = None
@@ -33,8 +37,9 @@ class AltimateCatalogTableMetadata(BaseModel):
33
37
 
34
38
 
35
39
  class AltimateCatalogColumnMetadata(BaseModel):
36
- class Config:
37
- extra = Extra.forbid
40
+ model_config = ConfigDict(
41
+ extra=Extra.forbid,
42
+ )
38
43
 
39
44
  type: str
40
45
  comment: Optional[Optional[str]] = None
@@ -43,8 +48,9 @@ class AltimateCatalogColumnMetadata(BaseModel):
43
48
 
44
49
 
45
50
  class AltimateCatalogStatsItem(BaseModel):
46
- class Config:
47
- extra = Extra.forbid
51
+ model_config = ConfigDict(
52
+ extra=Extra.forbid,
53
+ )
48
54
 
49
55
  id: str
50
56
  label: str
@@ -54,8 +60,9 @@ class AltimateCatalogStatsItem(BaseModel):
54
60
 
55
61
 
56
62
  class AltimateCatalogTable(BaseModel):
57
- class Config:
58
- extra = Extra.forbid
63
+ model_config = ConfigDict(
64
+ extra=Extra.forbid,
65
+ )
59
66
 
60
67
  metadata: AltimateCatalogTableMetadata
61
68
  columns: Dict[str, AltimateCatalogColumnMetadata]
@@ -64,8 +71,9 @@ class AltimateCatalogTable(BaseModel):
64
71
 
65
72
 
66
73
  class AltimateCatalogCatalogV1(BaseModel):
67
- class Config:
68
- extra = Extra.forbid
74
+ model_config = ConfigDict(
75
+ extra=Extra.forbid,
76
+ )
69
77
 
70
78
  metadata: AltimateCatalogMetadata
71
79
  nodes: Dict[str, AltimateCatalogTable]
@@ -19,7 +19,9 @@ from dbt_artifacts_parser.parsers.manifest.manifest_v10 import ManifestV10
19
19
  from dbt_artifacts_parser.parsers.manifest.manifest_v11 import ManifestV11
20
20
  from dbt_artifacts_parser.parsers.manifest.manifest_v11 import SupportedLanguage
21
21
  from pydantic import BaseModel
22
- from pydantic import Extra
22
+ from pydantic import ConfigDict
23
+
24
+ from datapilot.constants import Extra
23
25
 
24
26
 
25
27
  class DBTVersion(BaseModel):
@@ -46,16 +48,17 @@ Catalog = CatalogV1
46
48
 
47
49
 
48
50
  class AltimateDocs(BaseModel):
49
- class Config:
50
- extra = Extra.forbid
51
+ model_config = ConfigDict(
52
+ extra=Extra.forbid,
53
+ )
51
54
 
52
55
  show: Optional[bool] = True
53
56
  node_color: Optional[Optional[str]] = None
54
57
 
55
58
 
56
59
  class AltimateDependsOn(BaseModel):
57
- nodes: Optional[List[str]]
58
- macros: Optional[List[str]]
60
+ nodes: Optional[List[str]] = None
61
+ macros: Optional[List[str]] = None
59
62
 
60
63
 
61
64
  class AltimateManifestColumnInfo(BaseModel):
@@ -98,8 +101,9 @@ class AltimateAccess(Enum):
98
101
 
99
102
 
100
103
  class AltimateDBTContract(BaseModel):
101
- class Config:
102
- extra = Extra.forbid
104
+ model_config = ConfigDict(
105
+ extra=Extra.forbid,
106
+ )
103
107
 
104
108
  enforced: Optional[bool] = False
105
109
  alias_types: Optional[bool] = True
@@ -107,8 +111,9 @@ class AltimateDBTContract(BaseModel):
107
111
 
108
112
 
109
113
  class AltimateHook(BaseModel):
110
- class Config:
111
- extra = Extra.forbid
114
+ model_config = ConfigDict(
115
+ extra=Extra.forbid,
116
+ )
112
117
 
113
118
  sql: str
114
119
  transaction: Optional[bool] = True
@@ -117,8 +122,9 @@ class AltimateHook(BaseModel):
117
122
 
118
123
  # TODO: Need to add the rest of the fields
119
124
  class AltimateNodeConfig(BaseModel):
120
- class Config:
121
- extra = Extra.allow
125
+ model_config = ConfigDict(
126
+ extra=Extra.allow,
127
+ )
122
128
 
123
129
  _extra: Optional[Dict[str, Any]] = None
124
130
  enabled: Optional[bool] = True
@@ -203,8 +209,9 @@ class AltimateSourceConfig(BaseModel):
203
209
 
204
210
 
205
211
  class AltimateDeferRelation(BaseModel):
206
- class Config:
207
- extra = Extra.forbid
212
+ model_config = ConfigDict(
213
+ extra=Extra.forbid,
214
+ )
208
215
 
209
216
  database: Optional[str]
210
217
  schema_name: str
@@ -213,8 +220,9 @@ class AltimateDeferRelation(BaseModel):
213
220
 
214
221
 
215
222
  class AltimateSeedConfig(BaseModel):
216
- class Config:
217
- extra = Extra.allow
223
+ model_config = ConfigDict(
224
+ extra=Extra.allow,
225
+ )
218
226
 
219
227
  _extra: Optional[Dict[str, Any]] = None
220
228
  enabled: Optional[bool] = True
@@ -314,8 +322,9 @@ class AltimateExposureType(Enum):
314
322
 
315
323
 
316
324
  class AltimateOwner(BaseModel):
317
- class Config:
318
- extra = Extra.allow
325
+ model_config = ConfigDict(
326
+ extra=Extra.allow,
327
+ )
319
328
 
320
329
  _extra: Optional[Dict[str, Any]] = None
321
330
  email: Optional[Optional[str]] = None
@@ -329,8 +338,9 @@ class AltimateMaturityEnum(Enum):
329
338
 
330
339
 
331
340
  class AltimateRefArgs(BaseModel):
332
- class Config:
333
- extra = Extra.forbid
341
+ model_config = ConfigDict(
342
+ extra=Extra.forbid,
343
+ )
334
344
 
335
345
  name: str
336
346
  package: Optional[Optional[str]] = None
@@ -338,8 +348,9 @@ class AltimateRefArgs(BaseModel):
338
348
 
339
349
 
340
350
  class AltimateExposureConfig(BaseModel):
341
- class Config:
342
- extra = Extra.allow
351
+ model_config = ConfigDict(
352
+ extra=Extra.allow,
353
+ )
343
354
 
344
355
  _extra: Optional[Dict[str, Any]] = None
345
356
  enabled: Optional[bool] = True
@@ -371,8 +382,9 @@ class AltimateManifestExposureNode(BaseModel):
371
382
 
372
383
 
373
384
  class AltimateTestMetadata(BaseModel):
374
- class Config:
375
- extra = Extra.forbid
385
+ model_config = ConfigDict(
386
+ extra=Extra.forbid,
387
+ )
376
388
 
377
389
  name: str
378
390
  kwargs: Optional[Dict[str, Any]] = None
@@ -380,8 +392,9 @@ class AltimateTestMetadata(BaseModel):
380
392
 
381
393
 
382
394
  class AltimateTestConfig(BaseModel):
383
- class Config:
384
- extra = Extra.allow
395
+ model_config = ConfigDict(
396
+ extra=Extra.allow,
397
+ )
385
398
 
386
399
  _extra: Optional[Dict[str, Any]] = None
387
400
  enabled: Optional[bool] = True
@@ -433,8 +446,9 @@ class AltimateManifestTestNode(BaseModel):
433
446
 
434
447
 
435
448
  class AltimateMacroArgument(BaseModel):
436
- class Config:
437
- extra = Extra.forbid
449
+ model_config = ConfigDict(
450
+ extra=Extra.forbid,
451
+ )
438
452
 
439
453
  name: str
440
454
  type: Optional[Optional[str]] = None
@@ -1,4 +1,5 @@
1
1
  from typing import Dict
2
+ from typing import Optional
2
3
  from typing import Set
3
4
 
4
5
  from dbt_artifacts_parser.parsers.manifest.manifest_v10 import GenericTestNode
@@ -67,6 +68,7 @@ class ManifestV10Wrapper(BaseManifestWrapper):
67
68
  depends_on_macros = node.depends_on.macros if node.depends_on else None
68
69
  compiled_path = node.compiled_path
69
70
  compiled = node.compiled
71
+ compiled_code = node.compiled_code
70
72
  raw_code = node.raw_code
71
73
  language = node.language
72
74
  contract = AltimateDBTContract(**node.contract.__dict__) if node.contract else None
@@ -114,6 +116,7 @@ class ManifestV10Wrapper(BaseManifestWrapper):
114
116
  contract=contract,
115
117
  meta=node.meta,
116
118
  patch_path=node.patch_path,
119
+ access=node.access.value,
117
120
  )
118
121
 
119
122
  def _get_source(self, source: SourceNode) -> AltimateManifestSourceNode:
@@ -131,10 +134,10 @@ class ManifestV10Wrapper(BaseManifestWrapper):
131
134
  source_description=source.source_description,
132
135
  loader=source.loader,
133
136
  identifier=source.identifier,
134
- quoting=AltimateQuoting(**source.quoting.dict()) if source.quoting else None,
137
+ quoting=AltimateQuoting(**source.quoting.model_dump()) if source.quoting else None,
135
138
  loaded_at_field=source.loaded_at_field,
136
- freshness=AltimateFreshnessThreshold(**source.freshness.dict()) if source.freshness else None,
137
- external=AltimateExternalTable(**source.external.dict()) if source.external else None,
139
+ freshness=AltimateFreshnessThreshold(**source.freshness.model_dump()) if source.freshness else None,
140
+ external=AltimateExternalTable(**source.external.model_dump()) if source.external else None,
138
141
  description=source.description,
139
142
  columns={
140
143
  name: AltimateManifestColumnInfo(
@@ -151,7 +154,7 @@ class ManifestV10Wrapper(BaseManifestWrapper):
151
154
  relation_name=source.relation_name,
152
155
  source_meta=source.source_meta,
153
156
  tags=source.tags,
154
- config=AltimateSourceConfig(**source.config.dict()) if source.config else None,
157
+ config=AltimateSourceConfig(**source.config.model_dump()) if source.config else None,
155
158
  patch_path=source.patch_path,
156
159
  unrendered_config=source.unrendered_config,
157
160
  created_at=source.created_at,
@@ -175,9 +178,9 @@ class ManifestV10Wrapper(BaseManifestWrapper):
175
178
  ),
176
179
  description=macro.description,
177
180
  meta=macro.meta,
178
- docs=macro.docs,
181
+ docs=macro.docs.model_dump() if macro.docs else None,
179
182
  patch_path=macro.patch_path,
180
- arguments=[AltimateMacroArgument(**arg.dict()) for arg in macro.arguments] if macro.arguments else None,
183
+ arguments=[AltimateMacroArgument(**arg.model_dump()) for arg in macro.arguments] if macro.arguments else None,
181
184
  created_at=macro.created_at,
182
185
  supported_languages=macro.supported_languages,
183
186
  )
@@ -192,22 +195,24 @@ class ManifestV10Wrapper(BaseManifestWrapper):
192
195
  unique_id=exposure.unique_id,
193
196
  fqn=exposure.fqn,
194
197
  type=AltimateExposureType(exposure.type.value) if exposure.type else None,
195
- owner=AltimateOwner(**exposure.owner.dict()) if exposure.owner else None,
198
+ owner=AltimateOwner(**exposure.owner.model_dump()) if exposure.owner else None,
196
199
  description=exposure.description,
197
200
  label=exposure.label,
198
201
  maturity=AltimateMaturityEnum(exposure.maturity.value) if exposure.maturity else None,
199
202
  meta=exposure.meta,
200
203
  tags=exposure.tags,
201
- config=AltimateSourceConfig(**exposure.config.dict()) if exposure.config else None,
204
+ config=AltimateSourceConfig(**exposure.config.model_dump()) if exposure.config else None,
202
205
  unrendered_config=exposure.unrendered_config,
203
206
  url=exposure.url,
204
- depends_on=AltimateDependsOn(
205
- nodes=exposure.depends_on.nodes,
206
- macros=exposure.depends_on.macros,
207
- )
208
- if exposure.depends_on
209
- else None,
210
- refs=[AltimateRefArgs(**ref.dict()) for ref in exposure.refs] if exposure.refs else None,
207
+ depends_on=(
208
+ AltimateDependsOn(
209
+ nodes=exposure.depends_on.nodes,
210
+ macros=exposure.depends_on.macros,
211
+ )
212
+ if exposure.depends_on
213
+ else None
214
+ ),
215
+ refs=[AltimateRefArgs(**ref.model_dump()) for ref in exposure.refs] if exposure.refs else None,
211
216
  sources=exposure.sources,
212
217
  metrics=exposure.metrics,
213
218
  created_at=exposure.created_at,
@@ -217,7 +222,7 @@ class ManifestV10Wrapper(BaseManifestWrapper):
217
222
  test_metadata = None
218
223
  if isinstance(test, GenericTestNode):
219
224
  test_type = GENERIC
220
- test_metadata = AltimateTestMetadata(**test.test_metadata.dict()) if test.test_metadata else None
225
+ test_metadata = AltimateTestMetadata(**test.test_metadata.model_dump()) if test.test_metadata else None
221
226
  elif isinstance(test, SingularTestNode):
222
227
  test_type = SINGULAR
223
228
  else:
@@ -233,42 +238,48 @@ class ManifestV10Wrapper(BaseManifestWrapper):
233
238
  unique_id=test.unique_id,
234
239
  fqn=test.fqn,
235
240
  alias=test.alias,
236
- checksum=AltimateFileHash(
237
- name=test.checksum.name,
238
- checksum=test.checksum.checksum,
239
- )
240
- if test.checksum
241
- else None,
242
- config=AltimateTestConfig(**test.config.dict()) if test.config else None,
241
+ checksum=(
242
+ AltimateFileHash(
243
+ name=test.checksum.name,
244
+ checksum=test.checksum.checksum,
245
+ )
246
+ if test.checksum
247
+ else None
248
+ ),
249
+ config=AltimateTestConfig(**test.config.model_dump()) if test.config else None,
243
250
  description=test.description,
244
251
  tags=test.tags,
245
- columns={
246
- name: AltimateManifestColumnInfo(
247
- name=column.name,
248
- description=column.description,
249
- meta=column.meta,
250
- data_type=column.data_type,
251
- quote=column.quote,
252
- tags=column.tags,
253
- )
254
- for name, column in test.columns.items()
255
- }
256
- if test.columns
257
- else None,
252
+ columns=(
253
+ {
254
+ name: AltimateManifestColumnInfo(
255
+ name=column.name,
256
+ description=column.description,
257
+ meta=column.meta,
258
+ data_type=column.data_type,
259
+ quote=column.quote,
260
+ tags=column.tags,
261
+ )
262
+ for name, column in test.columns.items()
263
+ }
264
+ if test.columns
265
+ else None
266
+ ),
258
267
  meta=test.meta,
259
268
  relation_name=test.relation_name,
260
269
  group=test.group,
261
270
  raw_code=test.raw_code,
262
271
  language=test.language,
263
- refs=[AltimateRefArgs(**ref.dict()) for ref in test.refs] if test.refs else None,
272
+ refs=[AltimateRefArgs(**ref.model_dump()) for ref in test.refs] if test.refs else None,
264
273
  sources=test.sources,
265
274
  metrics=test.metrics,
266
- depends_on=AltimateDependsOn(
267
- nodes=test.depends_on.nodes,
268
- macros=test.depends_on.macros,
269
- )
270
- if test.depends_on
271
- else None,
275
+ depends_on=(
276
+ AltimateDependsOn(
277
+ nodes=test.depends_on.nodes,
278
+ macros=test.depends_on.macros,
279
+ )
280
+ if test.depends_on
281
+ else None
282
+ ),
272
283
  compiled_path=test.compiled_path,
273
284
  compiled=test.compiled,
274
285
  compiled_code=test.compiled_code,
@@ -286,31 +297,35 @@ class ManifestV10Wrapper(BaseManifestWrapper):
286
297
  unique_id=seed.unique_id,
287
298
  fqn=seed.fqn,
288
299
  alias=seed.alias,
289
- checksum=AltimateFileHash(
290
- name=seed.checksum.name,
291
- checksum=seed.checksum.checksum,
292
- )
293
- if seed.checksum
294
- else None,
295
- config=AltimateSeedConfig(**seed.config.dict()) if seed.config else None,
300
+ checksum=(
301
+ AltimateFileHash(
302
+ name=seed.checksum.name,
303
+ checksum=seed.checksum.checksum,
304
+ )
305
+ if seed.checksum
306
+ else None
307
+ ),
308
+ config=AltimateSeedConfig(**seed.config.model_dump()) if seed.config else None,
296
309
  description=seed.description,
297
310
  tags=seed.tags,
298
- columns={
299
- name: AltimateManifestColumnInfo(
300
- name=column.name,
301
- description=column.description,
302
- meta=column.meta,
303
- data_type=column.data_type,
304
- quote=column.quote,
305
- tags=column.tags,
306
- )
307
- for name, column in seed.columns.items()
308
- }
309
- if seed.columns
310
- else None,
311
+ columns=(
312
+ {
313
+ name: AltimateManifestColumnInfo(
314
+ name=column.name,
315
+ description=column.description,
316
+ meta=column.meta,
317
+ data_type=column.data_type,
318
+ quote=column.quote,
319
+ tags=column.tags,
320
+ )
321
+ for name, column in seed.columns.items()
322
+ }
323
+ if seed.columns
324
+ else None
325
+ ),
311
326
  meta=seed.meta,
312
327
  group=seed.group,
313
- docs=seed.docs.dict() if seed.docs else None,
328
+ docs=seed.docs.model_dump() if seed.docs else None,
314
329
  patch_path=seed.patch_path,
315
330
  build_path=seed.build_path,
316
331
  deferred=seed.deferred,
@@ -381,6 +396,9 @@ class ManifestV10Wrapper(BaseManifestWrapper):
381
396
  seeds[seed.unique_id] = self._get_seed(seed)
382
397
  return seeds
383
398
 
399
+ def get_adapter_type(self) -> Optional[str]:
400
+ return self.manifest.metadata.adapter_type
401
+
384
402
  def parent_to_child_map(self, nodes: Dict[str, AltimateManifestNode]) -> Dict[str, Set[str]]:
385
403
  """
386
404
  Current manifest contains information about parents