acryl-datahub 1.1.1rc3__py3-none-any.whl → 1.2.0__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 acryl-datahub might be problematic. Click here for more details.

Files changed (226) hide show
  1. {acryl_datahub-1.1.1rc3.dist-info → acryl_datahub-1.2.0.dist-info}/METADATA +2559 -2532
  2. {acryl_datahub-1.1.1rc3.dist-info → acryl_datahub-1.2.0.dist-info}/RECORD +226 -190
  3. {acryl_datahub-1.1.1rc3.dist-info → acryl_datahub-1.2.0.dist-info}/WHEEL +1 -1
  4. {acryl_datahub-1.1.1rc3.dist-info → acryl_datahub-1.2.0.dist-info}/entry_points.txt +2 -0
  5. datahub/_version.py +1 -1
  6. datahub/api/entities/dataset/dataset.py +2 -1
  7. datahub/api/entities/external/__init__.py +0 -0
  8. datahub/api/entities/external/external_entities.py +239 -0
  9. datahub/api/entities/external/external_tag.py +145 -0
  10. datahub/api/entities/external/lake_formation_external_entites.py +161 -0
  11. datahub/api/entities/external/restricted_text.py +247 -0
  12. datahub/api/entities/external/unity_catalog_external_entites.py +173 -0
  13. datahub/cli/check_cli.py +88 -7
  14. datahub/cli/cli_utils.py +63 -0
  15. datahub/cli/container_cli.py +5 -0
  16. datahub/cli/delete_cli.py +124 -27
  17. datahub/cli/docker_check.py +107 -12
  18. datahub/cli/docker_cli.py +149 -227
  19. datahub/cli/exists_cli.py +0 -2
  20. datahub/cli/get_cli.py +0 -2
  21. datahub/cli/iceberg_cli.py +5 -0
  22. datahub/cli/ingest_cli.py +12 -16
  23. datahub/cli/migrate.py +2 -0
  24. datahub/cli/put_cli.py +1 -4
  25. datahub/cli/quickstart_versioning.py +50 -7
  26. datahub/cli/specific/assertions_cli.py +0 -4
  27. datahub/cli/specific/datacontract_cli.py +0 -3
  28. datahub/cli/specific/dataproduct_cli.py +0 -11
  29. datahub/cli/specific/dataset_cli.py +1 -8
  30. datahub/cli/specific/forms_cli.py +0 -4
  31. datahub/cli/specific/group_cli.py +0 -2
  32. datahub/cli/specific/structuredproperties_cli.py +1 -4
  33. datahub/cli/specific/user_cli.py +0 -2
  34. datahub/cli/state_cli.py +0 -2
  35. datahub/cli/timeline_cli.py +0 -2
  36. datahub/emitter/response_helper.py +86 -1
  37. datahub/emitter/rest_emitter.py +71 -13
  38. datahub/entrypoints.py +4 -3
  39. datahub/ingestion/api/decorators.py +15 -3
  40. datahub/ingestion/api/report.py +332 -3
  41. datahub/ingestion/api/sink.py +3 -0
  42. datahub/ingestion/api/source.py +48 -44
  43. datahub/ingestion/autogenerated/__init__.py +0 -0
  44. datahub/ingestion/autogenerated/capability_summary.json +3449 -0
  45. datahub/ingestion/autogenerated/lineage.json +401 -0
  46. datahub/ingestion/autogenerated/lineage_helper.py +177 -0
  47. datahub/ingestion/extractor/schema_util.py +13 -4
  48. datahub/ingestion/glossary/classification_mixin.py +5 -0
  49. datahub/ingestion/graph/client.py +100 -15
  50. datahub/ingestion/graph/config.py +1 -0
  51. datahub/ingestion/reporting/datahub_ingestion_run_summary_provider.py +20 -10
  52. datahub/ingestion/run/pipeline.py +54 -2
  53. datahub/ingestion/sink/datahub_rest.py +13 -0
  54. datahub/ingestion/source/abs/source.py +1 -1
  55. datahub/ingestion/source/aws/aws_common.py +4 -0
  56. datahub/ingestion/source/aws/glue.py +489 -244
  57. datahub/ingestion/source/aws/tag_entities.py +292 -0
  58. datahub/ingestion/source/azure/azure_common.py +2 -2
  59. datahub/ingestion/source/bigquery_v2/bigquery.py +50 -23
  60. datahub/ingestion/source/bigquery_v2/bigquery_config.py +1 -1
  61. datahub/ingestion/source/bigquery_v2/bigquery_queries.py +1 -0
  62. datahub/ingestion/source/bigquery_v2/bigquery_schema_gen.py +2 -0
  63. datahub/ingestion/source/bigquery_v2/common.py +1 -1
  64. datahub/ingestion/source/bigquery_v2/profiler.py +4 -2
  65. datahub/ingestion/source/bigquery_v2/queries.py +3 -3
  66. datahub/ingestion/source/cassandra/cassandra.py +1 -1
  67. datahub/ingestion/source/cassandra/cassandra_profiling.py +6 -5
  68. datahub/ingestion/source/common/subtypes.py +45 -0
  69. datahub/ingestion/source/data_lake_common/object_store.py +115 -27
  70. datahub/ingestion/source/data_lake_common/path_spec.py +10 -21
  71. datahub/ingestion/source/datahub/config.py +11 -0
  72. datahub/ingestion/source/datahub/datahub_database_reader.py +187 -35
  73. datahub/ingestion/source/datahub/datahub_source.py +1 -1
  74. datahub/ingestion/source/dbt/dbt_cloud.py +10 -2
  75. datahub/ingestion/source/dbt/dbt_common.py +6 -2
  76. datahub/ingestion/source/dbt/dbt_core.py +3 -0
  77. datahub/ingestion/source/debug/__init__.py +0 -0
  78. datahub/ingestion/source/debug/datahub_debug.py +300 -0
  79. datahub/ingestion/source/dremio/dremio_api.py +114 -73
  80. datahub/ingestion/source/dremio/dremio_config.py +2 -0
  81. datahub/ingestion/source/dremio/dremio_reporting.py +23 -2
  82. datahub/ingestion/source/dremio/dremio_source.py +94 -81
  83. datahub/ingestion/source/dremio/dremio_sql_queries.py +82 -21
  84. datahub/ingestion/source/file.py +3 -0
  85. datahub/ingestion/source/fivetran/fivetran.py +34 -26
  86. datahub/ingestion/source/gcs/gcs_source.py +13 -2
  87. datahub/ingestion/source/ge_data_profiler.py +76 -28
  88. datahub/ingestion/source/ge_profiling_config.py +11 -0
  89. datahub/ingestion/source/hex/api.py +26 -1
  90. datahub/ingestion/source/iceberg/iceberg.py +3 -1
  91. datahub/ingestion/source/identity/azure_ad.py +1 -1
  92. datahub/ingestion/source/identity/okta.py +1 -14
  93. datahub/ingestion/source/kafka/kafka.py +16 -0
  94. datahub/ingestion/source/kafka_connect/sink_connectors.py +156 -47
  95. datahub/ingestion/source/kafka_connect/source_connectors.py +59 -4
  96. datahub/ingestion/source/looker/looker_source.py +1 -0
  97. datahub/ingestion/source/mlflow.py +11 -1
  98. datahub/ingestion/source/mock_data/__init__.py +0 -0
  99. datahub/ingestion/source/mock_data/datahub_mock_data.py +472 -0
  100. datahub/ingestion/source/mock_data/datahub_mock_data_report.py +12 -0
  101. datahub/ingestion/source/mock_data/table_naming_helper.py +91 -0
  102. datahub/ingestion/source/nifi.py +1 -1
  103. datahub/ingestion/source/openapi.py +12 -0
  104. datahub/ingestion/source/openapi_parser.py +56 -37
  105. datahub/ingestion/source/powerbi/powerbi.py +1 -5
  106. datahub/ingestion/source/powerbi/rest_api_wrapper/powerbi_api.py +0 -1
  107. datahub/ingestion/source/powerbi_report_server/report_server.py +0 -23
  108. datahub/ingestion/source/preset.py +2 -2
  109. datahub/ingestion/source/qlik_sense/qlik_sense.py +1 -0
  110. datahub/ingestion/source/redshift/redshift.py +21 -1
  111. datahub/ingestion/source/redshift/usage.py +4 -3
  112. datahub/ingestion/source/s3/report.py +4 -2
  113. datahub/ingestion/source/s3/source.py +367 -115
  114. datahub/ingestion/source/sac/sac.py +3 -1
  115. datahub/ingestion/source/salesforce.py +6 -3
  116. datahub/ingestion/source/sigma/sigma.py +7 -1
  117. datahub/ingestion/source/slack/slack.py +2 -1
  118. datahub/ingestion/source/snowflake/snowflake_config.py +43 -7
  119. datahub/ingestion/source/snowflake/snowflake_queries.py +348 -82
  120. datahub/ingestion/source/snowflake/snowflake_summary.py +5 -0
  121. datahub/ingestion/source/snowflake/snowflake_usage_v2.py +8 -2
  122. datahub/ingestion/source/snowflake/snowflake_utils.py +2 -7
  123. datahub/ingestion/source/snowflake/snowflake_v2.py +33 -8
  124. datahub/ingestion/source/snowflake/stored_proc_lineage.py +143 -0
  125. datahub/ingestion/source/sql/athena.py +119 -11
  126. datahub/ingestion/source/sql/athena_properties_extractor.py +777 -0
  127. datahub/ingestion/source/sql/clickhouse.py +3 -1
  128. datahub/ingestion/source/sql/cockroachdb.py +0 -1
  129. datahub/ingestion/source/sql/hana.py +3 -1
  130. datahub/ingestion/source/sql/hive_metastore.py +3 -11
  131. datahub/ingestion/source/sql/mariadb.py +0 -1
  132. datahub/ingestion/source/sql/mssql/source.py +239 -34
  133. datahub/ingestion/source/sql/mysql.py +0 -1
  134. datahub/ingestion/source/sql/oracle.py +1 -1
  135. datahub/ingestion/source/sql/postgres.py +0 -1
  136. datahub/ingestion/source/sql/sql_common.py +121 -34
  137. datahub/ingestion/source/sql/sql_generic_profiler.py +2 -1
  138. datahub/ingestion/source/sql/teradata.py +997 -235
  139. datahub/ingestion/source/sql/vertica.py +10 -6
  140. datahub/ingestion/source/sql_queries.py +2 -2
  141. datahub/ingestion/source/state/stateful_ingestion_base.py +1 -1
  142. datahub/ingestion/source/superset.py +58 -3
  143. datahub/ingestion/source/tableau/tableau.py +58 -37
  144. datahub/ingestion/source/tableau/tableau_common.py +4 -2
  145. datahub/ingestion/source/tableau/tableau_constant.py +0 -4
  146. datahub/ingestion/source/unity/config.py +5 -0
  147. datahub/ingestion/source/unity/proxy.py +118 -0
  148. datahub/ingestion/source/unity/source.py +195 -17
  149. datahub/ingestion/source/unity/tag_entities.py +295 -0
  150. datahub/ingestion/source/usage/clickhouse_usage.py +4 -1
  151. datahub/ingestion/source/usage/starburst_trino_usage.py +3 -0
  152. datahub/ingestion/transformer/add_dataset_ownership.py +18 -2
  153. datahub/integrations/assertion/snowflake/compiler.py +4 -3
  154. datahub/metadata/_internal_schema_classes.py +1446 -559
  155. datahub/metadata/_urns/urn_defs.py +1721 -1553
  156. datahub/metadata/com/linkedin/pegasus2avro/application/__init__.py +19 -0
  157. datahub/metadata/com/linkedin/pegasus2avro/identity/__init__.py +2 -0
  158. datahub/metadata/com/linkedin/pegasus2avro/logical/__init__.py +15 -0
  159. datahub/metadata/com/linkedin/pegasus2avro/metadata/key/__init__.py +4 -0
  160. datahub/metadata/com/linkedin/pegasus2avro/module/__init__.py +27 -0
  161. datahub/metadata/com/linkedin/pegasus2avro/settings/global/__init__.py +4 -0
  162. datahub/metadata/com/linkedin/pegasus2avro/template/__init__.py +25 -0
  163. datahub/metadata/schema.avsc +18055 -17802
  164. datahub/metadata/schemas/ApplicationKey.avsc +31 -0
  165. datahub/metadata/schemas/ApplicationProperties.avsc +72 -0
  166. datahub/metadata/schemas/Applications.avsc +38 -0
  167. datahub/metadata/schemas/ChartKey.avsc +1 -0
  168. datahub/metadata/schemas/ContainerKey.avsc +1 -0
  169. datahub/metadata/schemas/ContainerProperties.avsc +8 -0
  170. datahub/metadata/schemas/CorpUserSettings.avsc +41 -0
  171. datahub/metadata/schemas/DashboardKey.avsc +1 -0
  172. datahub/metadata/schemas/DataFlowInfo.avsc +8 -0
  173. datahub/metadata/schemas/DataFlowKey.avsc +1 -0
  174. datahub/metadata/schemas/DataHubPageModuleKey.avsc +21 -0
  175. datahub/metadata/schemas/DataHubPageModuleProperties.avsc +200 -0
  176. datahub/metadata/schemas/DataHubPageTemplateKey.avsc +21 -0
  177. datahub/metadata/schemas/DataHubPageTemplateProperties.avsc +175 -0
  178. datahub/metadata/schemas/DataHubPolicyInfo.avsc +12 -1
  179. datahub/metadata/schemas/DataJobInfo.avsc +8 -0
  180. datahub/metadata/schemas/DataJobKey.avsc +1 -0
  181. datahub/metadata/schemas/DataProcessKey.avsc +8 -0
  182. datahub/metadata/schemas/DataProductKey.avsc +1 -0
  183. datahub/metadata/schemas/DataProductProperties.avsc +1 -1
  184. datahub/metadata/schemas/DatasetKey.avsc +11 -1
  185. datahub/metadata/schemas/ExecutionRequestInput.avsc +5 -0
  186. datahub/metadata/schemas/GlobalSettingsInfo.avsc +62 -0
  187. datahub/metadata/schemas/GlossaryTermKey.avsc +1 -0
  188. datahub/metadata/schemas/IcebergWarehouseInfo.avsc +8 -0
  189. datahub/metadata/schemas/LogicalParent.avsc +140 -0
  190. datahub/metadata/schemas/MLFeatureKey.avsc +1 -0
  191. datahub/metadata/schemas/MLFeatureTableKey.avsc +1 -0
  192. datahub/metadata/schemas/MLModelDeploymentKey.avsc +8 -0
  193. datahub/metadata/schemas/MLModelGroupKey.avsc +9 -0
  194. datahub/metadata/schemas/MLModelKey.avsc +9 -0
  195. datahub/metadata/schemas/MLPrimaryKeyKey.avsc +1 -0
  196. datahub/metadata/schemas/MetadataChangeEvent.avsc +20 -1
  197. datahub/metadata/schemas/NotebookKey.avsc +1 -0
  198. datahub/metadata/schemas/QuerySubjects.avsc +1 -12
  199. datahub/metadata/schemas/SchemaFieldKey.avsc +2 -1
  200. datahub/sdk/__init__.py +6 -0
  201. datahub/sdk/_all_entities.py +11 -0
  202. datahub/sdk/_shared.py +118 -1
  203. datahub/sdk/chart.py +315 -0
  204. datahub/sdk/container.py +7 -0
  205. datahub/sdk/dashboard.py +432 -0
  206. datahub/sdk/dataflow.py +309 -0
  207. datahub/sdk/datajob.py +367 -0
  208. datahub/sdk/dataset.py +8 -2
  209. datahub/sdk/entity_client.py +90 -2
  210. datahub/sdk/lineage_client.py +683 -82
  211. datahub/sdk/main_client.py +46 -16
  212. datahub/sdk/mlmodel.py +101 -38
  213. datahub/sdk/mlmodelgroup.py +7 -0
  214. datahub/sdk/search_client.py +4 -3
  215. datahub/specific/chart.py +1 -1
  216. datahub/specific/dataproduct.py +4 -0
  217. datahub/sql_parsing/sql_parsing_aggregator.py +29 -17
  218. datahub/sql_parsing/sqlglot_lineage.py +62 -13
  219. datahub/telemetry/telemetry.py +17 -11
  220. datahub/testing/sdk_v2_helpers.py +7 -1
  221. datahub/upgrade/upgrade.py +46 -13
  222. datahub/utilities/server_config_util.py +8 -0
  223. datahub/utilities/sqlalchemy_query_combiner.py +5 -2
  224. datahub/utilities/stats_collections.py +4 -0
  225. {acryl_datahub-1.1.1rc3.dist-info → acryl_datahub-1.2.0.dist-info}/licenses/LICENSE +0 -0
  226. {acryl_datahub-1.1.1rc3.dist-info → acryl_datahub-1.2.0.dist-info}/top_level.txt +0 -0
datahub/sdk/chart.py ADDED
@@ -0,0 +1,315 @@
1
+ from __future__ import annotations
2
+
3
+ from datetime import datetime
4
+ from typing import Dict, List, Optional, Type, Union
5
+
6
+ from typing_extensions import Self
7
+
8
+ import datahub.metadata.schema_classes as models
9
+ from datahub.emitter.enum_helpers import get_enum_options
10
+ from datahub.metadata.urns import ChartUrn, DatasetUrn, Urn
11
+ from datahub.sdk._shared import (
12
+ DataPlatformInstanceUrnOrStr,
13
+ DataPlatformUrnOrStr,
14
+ DatasetUrnOrStr,
15
+ DomainInputType,
16
+ HasContainer,
17
+ HasDomain,
18
+ HasInstitutionalMemory,
19
+ HasOwnership,
20
+ HasPlatformInstance,
21
+ HasSubtype,
22
+ HasTags,
23
+ HasTerms,
24
+ LinksInputType,
25
+ OwnersInputType,
26
+ TagsInputType,
27
+ TermsInputType,
28
+ )
29
+ from datahub.sdk.dataset import Dataset
30
+ from datahub.sdk.entity import Entity, ExtraAspectsType
31
+
32
+
33
+ class Chart(
34
+ HasPlatformInstance,
35
+ HasSubtype,
36
+ HasOwnership,
37
+ HasContainer,
38
+ HasInstitutionalMemory,
39
+ HasTags,
40
+ HasTerms,
41
+ HasDomain,
42
+ Entity,
43
+ ):
44
+ """Represents a chart in DataHub."""
45
+
46
+ __slots__ = ()
47
+
48
+ @classmethod
49
+ def get_urn_type(cls) -> Type[ChartUrn]:
50
+ """Get the URN type for charts.
51
+ Returns:
52
+ The ChartUrn class.
53
+ """
54
+ return ChartUrn
55
+
56
+ def __init__(
57
+ self,
58
+ *,
59
+ # Identity.
60
+ name: str,
61
+ platform: DataPlatformUrnOrStr,
62
+ display_name: Optional[str] = None,
63
+ platform_instance: Optional[DataPlatformInstanceUrnOrStr] = None,
64
+ # Chart properties.
65
+ description: Optional[str] = "",
66
+ external_url: Optional[str] = None,
67
+ chart_url: Optional[str] = None,
68
+ custom_properties: Optional[Dict[str, str]] = None,
69
+ last_modified: Optional[datetime] = None,
70
+ last_refreshed: Optional[datetime] = None,
71
+ chart_type: Optional[Union[str, models.ChartTypeClass]] = None,
72
+ access: Optional[str] = None,
73
+ # Standard aspects.
74
+ subtype: Optional[str] = None,
75
+ owners: Optional[OwnersInputType] = None,
76
+ links: Optional[LinksInputType] = None,
77
+ tags: Optional[TagsInputType] = None,
78
+ terms: Optional[TermsInputType] = None,
79
+ domain: Optional[DomainInputType] = None,
80
+ input_datasets: Optional[List[Union[DatasetUrnOrStr, Dataset]]] = None,
81
+ extra_aspects: ExtraAspectsType = None,
82
+ ):
83
+ """Initialize a new Chart instance."""
84
+ urn = ChartUrn.create_from_ids(
85
+ platform=str(platform),
86
+ name=name,
87
+ platform_instance=str(platform_instance) if platform_instance else None,
88
+ )
89
+ super().__init__(urn)
90
+ self._set_extra_aspects(extra_aspects)
91
+
92
+ self._set_platform_instance(platform, platform_instance)
93
+
94
+ # Set additional properties
95
+ if external_url is not None:
96
+ self.set_external_url(external_url)
97
+ if chart_url is not None:
98
+ self.set_chart_url(chart_url)
99
+ if custom_properties is not None:
100
+ self.set_custom_properties(custom_properties)
101
+ if last_refreshed is not None:
102
+ self.set_last_refreshed(last_refreshed)
103
+ if chart_type is not None:
104
+ self.set_chart_type(chart_type)
105
+ if access is not None:
106
+ self.set_access(access)
107
+ if subtype is not None:
108
+ self.set_subtype(subtype)
109
+ if owners is not None:
110
+ self.set_owners(owners)
111
+ if links is not None:
112
+ self.set_links(links)
113
+ if tags is not None:
114
+ self.set_tags(tags)
115
+ if terms is not None:
116
+ self.set_terms(terms)
117
+ if domain is not None:
118
+ self.set_domain(domain)
119
+ if last_modified is not None:
120
+ self.set_last_modified(last_modified)
121
+ if input_datasets is not None:
122
+ self.set_input_datasets(input_datasets)
123
+ if description is not None:
124
+ self.set_description(description)
125
+ if display_name is not None:
126
+ self.set_display_name(display_name)
127
+
128
+ @classmethod
129
+ def _new_from_graph(cls, urn: Urn, current_aspects: models.AspectBag) -> Self:
130
+ assert isinstance(urn, ChartUrn)
131
+ entity = cls(
132
+ platform=urn.dashboard_tool,
133
+ name=urn.chart_id,
134
+ )
135
+ return entity._init_from_graph(current_aspects)
136
+
137
+ @property
138
+ def urn(self) -> ChartUrn:
139
+ assert isinstance(self._urn, ChartUrn)
140
+ return self._urn
141
+
142
+ def _ensure_chart_props(self) -> models.ChartInfoClass:
143
+ """Ensure chart properties exist, using a safer approach."""
144
+ return self._setdefault_aspect(
145
+ models.ChartInfoClass(
146
+ title=self.urn.chart_id,
147
+ description="",
148
+ lastModified=models.ChangeAuditStampsClass(),
149
+ )
150
+ )
151
+
152
+ @property
153
+ def name(self) -> str:
154
+ """Get the name of the chart."""
155
+ return self.urn.chart_id
156
+
157
+ @property
158
+ def title(self) -> str:
159
+ """Get the title of the chart."""
160
+ return self._ensure_chart_props().title
161
+
162
+ def set_title(self, title: str) -> None:
163
+ """Set the title of the chart."""
164
+ self._ensure_chart_props().title = title
165
+
166
+ @property
167
+ def description(self) -> Optional[str]:
168
+ """Get the description of the chart."""
169
+ return self._ensure_chart_props().description
170
+
171
+ def set_description(self, description: str) -> None:
172
+ """Set the description of the chart."""
173
+ self._ensure_chart_props().description = description
174
+
175
+ @property
176
+ def display_name(self) -> Optional[str]:
177
+ """Get the display name of the chart."""
178
+ return self.title
179
+
180
+ def set_display_name(self, display_name: str) -> None:
181
+ """Set the display name of the chart."""
182
+ self.set_title(display_name)
183
+
184
+ @property
185
+ def external_url(self) -> Optional[str]:
186
+ """Get the external URL of the chart."""
187
+ return self._ensure_chart_props().externalUrl
188
+
189
+ def set_external_url(self, external_url: str) -> None:
190
+ """Set the external URL of the chart."""
191
+ self._ensure_chart_props().externalUrl = external_url
192
+
193
+ @property
194
+ def chart_url(self) -> Optional[str]:
195
+ """Get the chart URL."""
196
+ return self._ensure_chart_props().chartUrl
197
+
198
+ def set_chart_url(self, chart_url: str) -> None:
199
+ """Set the chart URL."""
200
+ self._ensure_chart_props().chartUrl = chart_url
201
+
202
+ @property
203
+ def custom_properties(self) -> Dict[str, str]:
204
+ """Get the custom properties of the chart."""
205
+ return self._ensure_chart_props().customProperties
206
+
207
+ def set_custom_properties(self, custom_properties: Dict[str, str]) -> None:
208
+ """Set the custom properties of the chart."""
209
+ self._ensure_chart_props().customProperties = custom_properties
210
+
211
+ @property
212
+ def last_modified(self) -> Optional[datetime]:
213
+ """Get the last modification timestamp of the chart."""
214
+ last_modified_time = self._ensure_chart_props().lastModified.lastModified.time
215
+ if not last_modified_time:
216
+ return None
217
+ return datetime.fromtimestamp(last_modified_time)
218
+
219
+ def set_last_modified(self, last_modified: datetime) -> None:
220
+ """Set the last modification timestamp of the chart."""
221
+ chart_props = self._ensure_chart_props()
222
+ chart_props.lastModified = models.ChangeAuditStampsClass(
223
+ lastModified=models.AuditStampClass(
224
+ time=int(last_modified.timestamp()),
225
+ actor="urn:li:corpuser:datahub",
226
+ )
227
+ )
228
+
229
+ @property
230
+ def last_refreshed(self) -> Optional[datetime]:
231
+ """Get the last refresh timestamp of the chart."""
232
+ last_refreshed_time = self._ensure_chart_props().lastRefreshed
233
+ return (
234
+ datetime.fromtimestamp(last_refreshed_time)
235
+ if last_refreshed_time is not None
236
+ else None
237
+ )
238
+
239
+ def set_last_refreshed(self, last_refreshed: datetime) -> None:
240
+ """Set the last refresh timestamp of the chart."""
241
+ chart_props = self._ensure_chart_props()
242
+ chart_props.lastRefreshed = int(last_refreshed.timestamp())
243
+
244
+ @property
245
+ def chart_type(self) -> Optional[str]:
246
+ """Get the type of the chart as a string."""
247
+ chart_type = self._ensure_chart_props().type
248
+ return str(chart_type) if chart_type is not None else None
249
+
250
+ def set_chart_type(self, chart_type: Union[str, models.ChartTypeClass]) -> None:
251
+ """Set the type of the chart."""
252
+ if isinstance(chart_type, str):
253
+ assert chart_type in get_enum_options(models.ChartTypeClass), (
254
+ f"Invalid chart type: {chart_type}"
255
+ )
256
+ self._ensure_chart_props().type = chart_type
257
+
258
+ @property
259
+ def access(self) -> Optional[str]:
260
+ """Get the access level of the chart as a string."""
261
+ access = self._ensure_chart_props().access
262
+ return str(access) if access is not None else None
263
+
264
+ def set_access(self, access: Union[str, models.AccessLevelClass]) -> None:
265
+ """Set the access level of the chart."""
266
+ if isinstance(access, str):
267
+ assert access in get_enum_options(models.AccessLevelClass), (
268
+ f"Invalid access level: {access}"
269
+ )
270
+ self._ensure_chart_props().access = access
271
+
272
+ @property
273
+ def input_datasets(self) -> List[DatasetUrn]:
274
+ """Get the input datasets of the chart."""
275
+ props = self._ensure_chart_props()
276
+ # Convert all inputs to DatasetUrn
277
+ return [DatasetUrn.from_string(input_urn) for input_urn in (props.inputs or [])]
278
+
279
+ def set_input_datasets(
280
+ self, input_datasets: List[Union[DatasetUrnOrStr, Dataset]]
281
+ ) -> None:
282
+ """Set the input datasets of the chart."""
283
+ # Convert all inputs to strings
284
+ inputs = []
285
+ for input_dataset in input_datasets:
286
+ if isinstance(input_dataset, Dataset):
287
+ inputs.append(str(input_dataset.urn))
288
+ else:
289
+ inputs.append(str(input_dataset))
290
+ self._ensure_chart_props().inputs = inputs
291
+
292
+ def add_input_dataset(self, input_dataset: Union[DatasetUrnOrStr, Dataset]) -> None:
293
+ """Add an input to the chart."""
294
+ if isinstance(input_dataset, Dataset):
295
+ input_dataset_urn = input_dataset.urn
296
+ elif isinstance(input_dataset, str):
297
+ input_dataset_urn = DatasetUrn.from_string(input_dataset)
298
+ else: # isinstance(input_dataset, DatasetUrn)
299
+ input_dataset_urn = input_dataset
300
+
301
+ chart_props = self._ensure_chart_props()
302
+ inputs = chart_props.inputs or []
303
+ if str(input_dataset_urn) not in inputs:
304
+ inputs.append(str(input_dataset_urn))
305
+ chart_props.inputs = inputs
306
+
307
+ def remove_input_dataset(
308
+ self, input_dataset: Union[DatasetUrnOrStr, Dataset]
309
+ ) -> None:
310
+ """Remove an input from the chart."""
311
+ chart_props = self._ensure_chart_props()
312
+ inputs = chart_props.inputs or []
313
+ if input_dataset in inputs:
314
+ inputs.remove(str(input_dataset))
315
+ chart_props.inputs = inputs
datahub/sdk/container.py CHANGED
@@ -23,12 +23,14 @@ from datahub.sdk._shared import (
23
23
  HasInstitutionalMemory,
24
24
  HasOwnership,
25
25
  HasPlatformInstance,
26
+ HasStructuredProperties,
26
27
  HasSubtype,
27
28
  HasTags,
28
29
  HasTerms,
29
30
  LinksInputType,
30
31
  OwnersInputType,
31
32
  ParentContainerInputType,
33
+ StructuredPropertyInputType,
32
34
  TagsInputType,
33
35
  TermsInputType,
34
36
  make_time_stamp,
@@ -44,6 +46,7 @@ class Container(
44
46
  HasContainer,
45
47
  HasOwnership,
46
48
  HasInstitutionalMemory,
49
+ HasStructuredProperties,
47
50
  HasTags,
48
51
  HasTerms,
49
52
  HasDomain,
@@ -78,6 +81,7 @@ class Container(
78
81
  tags: Optional[TagsInputType] = None,
79
82
  terms: Optional[TermsInputType] = None,
80
83
  domain: Optional[DomainInputType] = None,
84
+ structured_properties: Optional[StructuredPropertyInputType] = None,
81
85
  extra_aspects: ExtraAspectsType = None,
82
86
  ):
83
87
  # Hack: while the type annotations say container_key is always a ContainerKey,
@@ -145,6 +149,9 @@ class Container(
145
149
  self.set_terms(terms)
146
150
  if domain is not None:
147
151
  self.set_domain(domain)
152
+ if structured_properties is not None:
153
+ for key, value in structured_properties.items():
154
+ self.set_structured_property(property_urn=key, values=value)
148
155
 
149
156
  @classmethod
150
157
  def _new_from_graph(cls, urn: Urn, current_aspects: models.AspectBag) -> Self: