acryl-datahub 0.15.0rc24__py3-none-any.whl → 0.15.0.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 acryl-datahub might be problematic. Click here for more details.

Files changed (120) hide show
  1. {acryl_datahub-0.15.0rc24.dist-info → acryl_datahub-0.15.0.1.dist-info}/METADATA +2408 -2412
  2. {acryl_datahub-0.15.0rc24.dist-info → acryl_datahub-0.15.0.1.dist-info}/RECORD +116 -106
  3. {acryl_datahub-0.15.0rc24.dist-info → acryl_datahub-0.15.0.1.dist-info}/WHEEL +1 -1
  4. {acryl_datahub-0.15.0rc24.dist-info → acryl_datahub-0.15.0.1.dist-info}/entry_points.txt +1 -1
  5. datahub/__init__.py +1 -1
  6. datahub/api/circuit_breaker/assertion_circuit_breaker.py +5 -4
  7. datahub/api/entities/structuredproperties/structuredproperties.py +20 -8
  8. datahub/configuration/common.py +2 -5
  9. datahub/configuration/source_common.py +13 -0
  10. datahub/emitter/mce_builder.py +20 -4
  11. datahub/emitter/mcp_builder.py +2 -7
  12. datahub/emitter/mcp_patch_builder.py +37 -13
  13. datahub/emitter/rest_emitter.py +25 -3
  14. datahub/ingestion/api/auto_work_units/auto_ensure_aspect_size.py +98 -0
  15. datahub/ingestion/api/closeable.py +3 -3
  16. datahub/ingestion/api/ingestion_job_checkpointing_provider_base.py +4 -7
  17. datahub/ingestion/api/report.py +4 -1
  18. datahub/ingestion/api/sink.py +4 -3
  19. datahub/ingestion/api/source.py +4 -0
  20. datahub/ingestion/api/source_helpers.py +2 -6
  21. datahub/ingestion/glossary/classifier.py +2 -3
  22. datahub/ingestion/graph/client.py +6 -3
  23. datahub/ingestion/reporting/datahub_ingestion_run_summary_provider.py +44 -1
  24. datahub/ingestion/source/aws/aws_common.py +231 -27
  25. datahub/ingestion/source/aws/glue.py +12 -2
  26. datahub/ingestion/source/bigquery_v2/bigquery.py +10 -18
  27. datahub/ingestion/source/bigquery_v2/bigquery_config.py +3 -9
  28. datahub/ingestion/source/bigquery_v2/bigquery_schema.py +5 -20
  29. datahub/ingestion/source/bigquery_v2/bigquery_schema_gen.py +11 -17
  30. datahub/ingestion/source/bigquery_v2/lineage.py +9 -22
  31. datahub/ingestion/source/datahub/config.py +22 -1
  32. datahub/ingestion/source/datahub/datahub_database_reader.py +3 -17
  33. datahub/ingestion/source/datahub/datahub_kafka_reader.py +2 -1
  34. datahub/ingestion/source/datahub/datahub_source.py +1 -1
  35. datahub/ingestion/source/dbt/dbt_cloud.py +10 -3
  36. datahub/ingestion/source/gc/datahub_gc.py +21 -5
  37. datahub/ingestion/source/gc/dataprocess_cleanup.py +23 -10
  38. datahub/ingestion/source/gc/execution_request_cleanup.py +61 -16
  39. datahub/ingestion/source/gc/soft_deleted_entity_cleanup.py +178 -83
  40. datahub/ingestion/source/iceberg/iceberg.py +27 -1
  41. datahub/ingestion/source/iceberg/iceberg_common.py +4 -0
  42. datahub/ingestion/source/kafka_connect/__init__.py +0 -0
  43. datahub/ingestion/source/kafka_connect/common.py +202 -0
  44. datahub/ingestion/source/kafka_connect/kafka_connect.py +367 -0
  45. datahub/ingestion/source/kafka_connect/sink_connectors.py +341 -0
  46. datahub/ingestion/source/kafka_connect/source_connectors.py +570 -0
  47. datahub/ingestion/source/looker/looker_common.py +63 -2
  48. datahub/ingestion/source/looker/looker_dataclasses.py +7 -9
  49. datahub/ingestion/source/looker/looker_lib_wrapper.py +13 -1
  50. datahub/ingestion/source/looker/looker_source.py +31 -4
  51. datahub/ingestion/source/looker/looker_usage.py +23 -17
  52. datahub/ingestion/source/mlflow.py +30 -5
  53. datahub/ingestion/source/mode.py +40 -27
  54. datahub/ingestion/source/powerbi/config.py +1 -14
  55. datahub/ingestion/source/powerbi/dataplatform_instance_resolver.py +1 -1
  56. datahub/ingestion/source/powerbi/m_query/pattern_handler.py +1 -1
  57. datahub/ingestion/source/powerbi/powerbi-lexical-grammar.rule +16 -2
  58. datahub/ingestion/source/powerbi/rest_api_wrapper/data_resolver.py +16 -15
  59. datahub/ingestion/source/s3/source.py +1 -1
  60. datahub/ingestion/source/snowflake/snowflake_config.py +13 -34
  61. datahub/ingestion/source/snowflake/snowflake_lineage_v2.py +14 -64
  62. datahub/ingestion/source/snowflake/snowflake_queries.py +44 -14
  63. datahub/ingestion/source/snowflake/snowflake_query.py +5 -10
  64. datahub/ingestion/source/snowflake/snowflake_schema_gen.py +53 -7
  65. datahub/ingestion/source/snowflake/snowflake_shares.py +1 -1
  66. datahub/ingestion/source/snowflake/snowflake_usage_v2.py +2 -5
  67. datahub/ingestion/source/snowflake/snowflake_utils.py +22 -18
  68. datahub/ingestion/source/snowflake/snowflake_v2.py +38 -34
  69. datahub/ingestion/source/sql/hive.py +621 -8
  70. datahub/ingestion/source/sql/hive_metastore.py +7 -0
  71. datahub/ingestion/source/sql/mssql/job_models.py +30 -1
  72. datahub/ingestion/source/sql/mssql/source.py +15 -1
  73. datahub/ingestion/source/sql/sql_common.py +41 -102
  74. datahub/ingestion/source/sql/sql_generic_profiler.py +5 -6
  75. datahub/ingestion/source/sql/sql_report.py +2 -0
  76. datahub/ingestion/source/state/checkpoint.py +2 -1
  77. datahub/ingestion/source/tableau/tableau.py +122 -45
  78. datahub/ingestion/source/tableau/tableau_common.py +18 -0
  79. datahub/ingestion/source/tableau/tableau_constant.py +3 -1
  80. datahub/ingestion/source/tableau/tableau_server_wrapper.py +6 -2
  81. datahub/ingestion/source/tableau/tableau_validation.py +1 -1
  82. datahub/ingestion/source/unity/proxy.py +8 -27
  83. datahub/ingestion/source/usage/usage_common.py +15 -1
  84. datahub/ingestion/source_report/ingestion_stage.py +3 -0
  85. datahub/metadata/_schema_classes.py +256 -3
  86. datahub/metadata/_urns/urn_defs.py +168 -168
  87. datahub/metadata/com/linkedin/pegasus2avro/common/__init__.py +4 -0
  88. datahub/metadata/com/linkedin/pegasus2avro/ml/metadata/__init__.py +2 -0
  89. datahub/metadata/schema.avsc +252 -33
  90. datahub/metadata/schemas/DataJobKey.avsc +2 -1
  91. datahub/metadata/schemas/DataProcessInstanceKey.avsc +5 -1
  92. datahub/metadata/schemas/DataProcessInstanceOutput.avsc +2 -1
  93. datahub/metadata/schemas/DataTransformLogic.avsc +63 -0
  94. datahub/metadata/schemas/MLModelGroupProperties.avsc +82 -0
  95. datahub/metadata/schemas/MLModelProperties.avsc +62 -2
  96. datahub/metadata/schemas/MLTrainingRunProperties.avsc +171 -0
  97. datahub/metadata/schemas/MetadataChangeEvent.avsc +94 -2
  98. datahub/specific/aspect_helpers/__init__.py +0 -0
  99. datahub/specific/aspect_helpers/custom_properties.py +79 -0
  100. datahub/specific/aspect_helpers/ownership.py +67 -0
  101. datahub/specific/aspect_helpers/structured_properties.py +72 -0
  102. datahub/specific/aspect_helpers/tags.py +42 -0
  103. datahub/specific/aspect_helpers/terms.py +43 -0
  104. datahub/specific/chart.py +28 -184
  105. datahub/specific/dashboard.py +31 -196
  106. datahub/specific/datajob.py +34 -189
  107. datahub/specific/dataproduct.py +24 -86
  108. datahub/specific/dataset.py +48 -133
  109. datahub/specific/form.py +12 -32
  110. datahub/specific/structured_property.py +9 -9
  111. datahub/sql_parsing/sql_parsing_aggregator.py +10 -9
  112. datahub/sql_parsing/sqlglot_lineage.py +15 -5
  113. datahub/sql_parsing/tool_meta_extractor.py +119 -5
  114. datahub/utilities/time.py +8 -3
  115. datahub/utilities/urns/_urn_base.py +5 -7
  116. datahub/ingestion/source/kafka/kafka_connect.py +0 -1468
  117. datahub/specific/custom_properties.py +0 -37
  118. datahub/specific/ownership.py +0 -48
  119. datahub/specific/structured_properties.py +0 -53
  120. {acryl_datahub-0.15.0rc24.dist-info → acryl_datahub-0.15.0.1.dist-info}/top_level.txt +0 -0
@@ -37,6 +37,21 @@
37
37
  "default": null,
38
38
  "doc": "URL where the reference exist"
39
39
  },
40
+ {
41
+ "Searchable": {
42
+ "boostScore": 10.0,
43
+ "enableAutocomplete": true,
44
+ "fieldType": "WORD_GRAM",
45
+ "queryByDefault": true
46
+ },
47
+ "type": [
48
+ "null",
49
+ "string"
50
+ ],
51
+ "name": "name",
52
+ "default": null,
53
+ "doc": "Display name of the MLModel"
54
+ },
40
55
  {
41
56
  "Searchable": {
42
57
  "fieldType": "TEXT",
@@ -51,6 +66,7 @@
51
66
  "doc": "Documentation of the MLModel"
52
67
  },
53
68
  {
69
+ "deprecated": true,
54
70
  "type": [
55
71
  "null",
56
72
  "long"
@@ -59,6 +75,49 @@
59
75
  "default": null,
60
76
  "doc": "Date when the MLModel was developed"
61
77
  },
78
+ {
79
+ "type": [
80
+ "null",
81
+ {
82
+ "type": "record",
83
+ "name": "TimeStamp",
84
+ "namespace": "com.linkedin.pegasus2avro.common",
85
+ "fields": [
86
+ {
87
+ "type": "long",
88
+ "name": "time",
89
+ "doc": "When did the event occur"
90
+ },
91
+ {
92
+ "java": {
93
+ "class": "com.linkedin.pegasus2avro.common.urn.Urn"
94
+ },
95
+ "type": [
96
+ "null",
97
+ "string"
98
+ ],
99
+ "name": "actor",
100
+ "default": null,
101
+ "doc": "Optional: The actor urn involved in the event.",
102
+ "Urn": "Urn"
103
+ }
104
+ ],
105
+ "doc": "A standard event timestamp"
106
+ }
107
+ ],
108
+ "name": "created",
109
+ "default": null,
110
+ "doc": "Audit stamp containing who created this and when"
111
+ },
112
+ {
113
+ "type": [
114
+ "null",
115
+ "com.linkedin.pegasus2avro.common.TimeStamp"
116
+ ],
117
+ "name": "lastModified",
118
+ "default": null,
119
+ "doc": "Date when the MLModel was last modified"
120
+ },
62
121
  {
63
122
  "type": [
64
123
  "null",
@@ -291,7 +350,8 @@
291
350
  "Relationship": {
292
351
  "/*": {
293
352
  "entityTypes": [
294
- "dataJob"
353
+ "dataJob",
354
+ "dataProcessInstance"
295
355
  ],
296
356
  "isLineage": true,
297
357
  "name": "TrainedBy"
@@ -306,7 +366,7 @@
306
366
  ],
307
367
  "name": "trainingJobs",
308
368
  "default": null,
309
- "doc": "List of jobs (if any) used to train the model",
369
+ "doc": "List of jobs (if any) used to train the model. Visible in Lineage. Note that ML Models can also be specified as the output of a specific Data Process Instances (runs) via the DataProcessInstanceOutputs aspect.",
310
370
  "Urn": "Urn",
311
371
  "urn_is_array": true
312
372
  },
@@ -0,0 +1,171 @@
1
+ {
2
+ "type": "record",
3
+ "Aspect": {
4
+ "name": "mlTrainingRunProperties"
5
+ },
6
+ "name": "MLTrainingRunProperties",
7
+ "namespace": "com.linkedin.pegasus2avro.ml.metadata",
8
+ "fields": [
9
+ {
10
+ "Searchable": {
11
+ "/*": {
12
+ "fieldType": "TEXT",
13
+ "queryByDefault": true
14
+ }
15
+ },
16
+ "type": {
17
+ "type": "map",
18
+ "values": "string"
19
+ },
20
+ "name": "customProperties",
21
+ "default": {},
22
+ "doc": "Custom property bag."
23
+ },
24
+ {
25
+ "Searchable": {
26
+ "fieldType": "KEYWORD"
27
+ },
28
+ "java": {
29
+ "class": "com.linkedin.pegasus2avro.common.url.Url",
30
+ "coercerClass": "com.linkedin.pegasus2avro.common.url.UrlCoercer"
31
+ },
32
+ "type": [
33
+ "null",
34
+ "string"
35
+ ],
36
+ "name": "externalUrl",
37
+ "default": null,
38
+ "doc": "URL where the reference exist"
39
+ },
40
+ {
41
+ "type": [
42
+ "null",
43
+ "string"
44
+ ],
45
+ "name": "id",
46
+ "default": null,
47
+ "doc": "Run Id of the ML Training Run"
48
+ },
49
+ {
50
+ "type": [
51
+ "null",
52
+ {
53
+ "type": "array",
54
+ "items": "string"
55
+ }
56
+ ],
57
+ "name": "outputUrls",
58
+ "default": null,
59
+ "doc": "List of URLs for the Outputs of the ML Training Run"
60
+ },
61
+ {
62
+ "type": [
63
+ "null",
64
+ {
65
+ "type": "array",
66
+ "items": {
67
+ "type": "record",
68
+ "Aspect": {
69
+ "name": "mlHyperParam"
70
+ },
71
+ "name": "MLHyperParam",
72
+ "namespace": "com.linkedin.pegasus2avro.ml.metadata",
73
+ "fields": [
74
+ {
75
+ "type": "string",
76
+ "name": "name",
77
+ "doc": "Name of the MLHyperParam"
78
+ },
79
+ {
80
+ "type": [
81
+ "null",
82
+ "string"
83
+ ],
84
+ "name": "description",
85
+ "default": null,
86
+ "doc": "Documentation of the MLHyperParam"
87
+ },
88
+ {
89
+ "type": [
90
+ "null",
91
+ "string"
92
+ ],
93
+ "name": "value",
94
+ "default": null,
95
+ "doc": "The value of the MLHyperParam"
96
+ },
97
+ {
98
+ "type": [
99
+ "null",
100
+ "long"
101
+ ],
102
+ "name": "createdAt",
103
+ "default": null,
104
+ "doc": "Date when the MLHyperParam was developed"
105
+ }
106
+ ],
107
+ "doc": "Properties associated with an ML Hyper Param"
108
+ }
109
+ }
110
+ ],
111
+ "name": "hyperParams",
112
+ "default": null,
113
+ "doc": "Hyperparameters of the ML Training Run"
114
+ },
115
+ {
116
+ "type": [
117
+ "null",
118
+ {
119
+ "type": "array",
120
+ "items": {
121
+ "type": "record",
122
+ "Aspect": {
123
+ "name": "mlMetric"
124
+ },
125
+ "name": "MLMetric",
126
+ "namespace": "com.linkedin.pegasus2avro.ml.metadata",
127
+ "fields": [
128
+ {
129
+ "type": "string",
130
+ "name": "name",
131
+ "doc": "Name of the mlMetric"
132
+ },
133
+ {
134
+ "type": [
135
+ "null",
136
+ "string"
137
+ ],
138
+ "name": "description",
139
+ "default": null,
140
+ "doc": "Documentation of the mlMetric"
141
+ },
142
+ {
143
+ "type": [
144
+ "null",
145
+ "string"
146
+ ],
147
+ "name": "value",
148
+ "default": null,
149
+ "doc": "The value of the mlMetric"
150
+ },
151
+ {
152
+ "type": [
153
+ "null",
154
+ "long"
155
+ ],
156
+ "name": "createdAt",
157
+ "default": null,
158
+ "doc": "Date when the mlMetric was developed"
159
+ }
160
+ ],
161
+ "doc": "Properties associated with an ML Metric"
162
+ }
163
+ }
164
+ ],
165
+ "name": "trainingMetrics",
166
+ "default": null,
167
+ "doc": "Metrics of the ML Training Run"
168
+ }
169
+ ],
170
+ "doc": "The inputs and outputs of this training run"
171
+ }
@@ -5109,6 +5109,21 @@
5109
5109
  "default": null,
5110
5110
  "doc": "URL where the reference exist"
5111
5111
  },
5112
+ {
5113
+ "Searchable": {
5114
+ "boostScore": 10.0,
5115
+ "enableAutocomplete": true,
5116
+ "fieldType": "WORD_GRAM",
5117
+ "queryByDefault": true
5118
+ },
5119
+ "type": [
5120
+ "null",
5121
+ "string"
5122
+ ],
5123
+ "name": "name",
5124
+ "default": null,
5125
+ "doc": "Display name of the MLModel"
5126
+ },
5112
5127
  {
5113
5128
  "Searchable": {
5114
5129
  "fieldType": "TEXT",
@@ -5123,6 +5138,7 @@
5123
5138
  "doc": "Documentation of the MLModel"
5124
5139
  },
5125
5140
  {
5141
+ "deprecated": true,
5126
5142
  "type": [
5127
5143
  "null",
5128
5144
  "long"
@@ -5131,6 +5147,24 @@
5131
5147
  "default": null,
5132
5148
  "doc": "Date when the MLModel was developed"
5133
5149
  },
5150
+ {
5151
+ "type": [
5152
+ "null",
5153
+ "com.linkedin.pegasus2avro.common.TimeStamp"
5154
+ ],
5155
+ "name": "created",
5156
+ "default": null,
5157
+ "doc": "Audit stamp containing who created this and when"
5158
+ },
5159
+ {
5160
+ "type": [
5161
+ "null",
5162
+ "com.linkedin.pegasus2avro.common.TimeStamp"
5163
+ ],
5164
+ "name": "lastModified",
5165
+ "default": null,
5166
+ "doc": "Date when the MLModel was last modified"
5167
+ },
5134
5168
  {
5135
5169
  "type": [
5136
5170
  "null",
@@ -5363,7 +5397,8 @@
5363
5397
  "Relationship": {
5364
5398
  "/*": {
5365
5399
  "entityTypes": [
5366
- "dataJob"
5400
+ "dataJob",
5401
+ "dataProcessInstance"
5367
5402
  ],
5368
5403
  "isLineage": true,
5369
5404
  "name": "TrainedBy"
@@ -5378,7 +5413,7 @@
5378
5413
  ],
5379
5414
  "name": "trainingJobs",
5380
5415
  "default": null,
5381
- "doc": "List of jobs (if any) used to train the model",
5416
+ "doc": "List of jobs (if any) used to train the model. Visible in Lineage. Note that ML Models can also be specified as the output of a specific Data Process Instances (runs) via the DataProcessInstanceOutputs aspect.",
5382
5417
  "Urn": "Urn",
5383
5418
  "urn_is_array": true
5384
5419
  },
@@ -6804,6 +6839,21 @@
6804
6839
  "default": {},
6805
6840
  "doc": "Custom property bag."
6806
6841
  },
6842
+ {
6843
+ "Searchable": {
6844
+ "boostScore": 10.0,
6845
+ "enableAutocomplete": true,
6846
+ "fieldType": "WORD_GRAM",
6847
+ "queryByDefault": true
6848
+ },
6849
+ "type": [
6850
+ "null",
6851
+ "string"
6852
+ ],
6853
+ "name": "name",
6854
+ "default": null,
6855
+ "doc": "Display name of the MLModelGroup"
6856
+ },
6807
6857
  {
6808
6858
  "Searchable": {
6809
6859
  "fieldType": "TEXT",
@@ -6818,6 +6868,7 @@
6818
6868
  "doc": "Documentation of the MLModelGroup"
6819
6869
  },
6820
6870
  {
6871
+ "deprecated": true,
6821
6872
  "type": [
6822
6873
  "null",
6823
6874
  "long"
@@ -6826,6 +6877,47 @@
6826
6877
  "default": null,
6827
6878
  "doc": "Date when the MLModelGroup was developed"
6828
6879
  },
6880
+ {
6881
+ "type": [
6882
+ "null",
6883
+ "com.linkedin.pegasus2avro.common.TimeStamp"
6884
+ ],
6885
+ "name": "created",
6886
+ "default": null,
6887
+ "doc": "Time and Actor who created the MLModelGroup"
6888
+ },
6889
+ {
6890
+ "type": [
6891
+ "null",
6892
+ "com.linkedin.pegasus2avro.common.TimeStamp"
6893
+ ],
6894
+ "name": "lastModified",
6895
+ "default": null,
6896
+ "doc": "Date when the MLModelGroup was last modified"
6897
+ },
6898
+ {
6899
+ "Relationship": {
6900
+ "/*": {
6901
+ "entityTypes": [
6902
+ "dataJob"
6903
+ ],
6904
+ "isLineage": true,
6905
+ "name": "TrainedBy"
6906
+ }
6907
+ },
6908
+ "type": [
6909
+ "null",
6910
+ {
6911
+ "type": "array",
6912
+ "items": "string"
6913
+ }
6914
+ ],
6915
+ "name": "trainingJobs",
6916
+ "default": null,
6917
+ "doc": "List of jobs (if any) used to train the model group. Visible in Lineage.",
6918
+ "Urn": "Urn",
6919
+ "urn_is_array": true
6920
+ },
6829
6921
  {
6830
6922
  "type": [
6831
6923
  "null",
File without changes
@@ -0,0 +1,79 @@
1
+ from abc import abstractmethod
2
+ from typing import Dict, Optional, Tuple
3
+
4
+ from typing_extensions import Self
5
+
6
+ from datahub.emitter.mcp_patch_builder import MetadataPatchProposal, PatchPath
7
+
8
+
9
+ class HasCustomPropertiesPatch(MetadataPatchProposal):
10
+ @classmethod
11
+ @abstractmethod
12
+ def _custom_properties_location(self) -> Tuple[str, PatchPath]:
13
+ ...
14
+
15
+ def add_custom_property(self, key: str, value: str) -> Self:
16
+ """Add a custom property to the entity.
17
+
18
+ Args:
19
+ key: The key of the custom property.
20
+ value: The value of the custom property.
21
+
22
+ Returns:
23
+ The patch builder instance.
24
+ """
25
+ aspect_name, path = self._custom_properties_location()
26
+ self._add_patch(
27
+ aspect_name,
28
+ "add",
29
+ path=(*path, key),
30
+ value=value,
31
+ )
32
+ return self
33
+
34
+ def add_custom_properties(
35
+ self, custom_properties: Optional[Dict[str, str]] = None
36
+ ) -> Self:
37
+ if custom_properties is not None:
38
+ for key, value in custom_properties.items():
39
+ self.add_custom_property(key, value)
40
+ return self
41
+
42
+ def remove_custom_property(self, key: str) -> Self:
43
+ """Remove a custom property from the entity.
44
+
45
+ Args:
46
+ key: The key of the custom property to remove.
47
+
48
+ Returns:
49
+ The patch builder instance.
50
+ """
51
+ aspect_name, path = self._custom_properties_location()
52
+ self._add_patch(
53
+ aspect_name,
54
+ "remove",
55
+ path=(*path, key),
56
+ value={},
57
+ )
58
+ return self
59
+
60
+ def set_custom_properties(self, custom_properties: Dict[str, str]) -> Self:
61
+ """Sets the custom properties of the entity.
62
+
63
+ This method replaces all existing custom properties with the given dictionary.
64
+
65
+ Args:
66
+ custom_properties: A dictionary containing the custom properties to be set.
67
+
68
+ Returns:
69
+ The patch builder instance.
70
+ """
71
+
72
+ aspect_name, path = self._custom_properties_location()
73
+ self._add_patch(
74
+ aspect_name,
75
+ "add",
76
+ path=path,
77
+ value=custom_properties,
78
+ )
79
+ return self
@@ -0,0 +1,67 @@
1
+ from typing import List, Optional
2
+
3
+ from typing_extensions import Self
4
+
5
+ from datahub.emitter.mcp_patch_builder import MetadataPatchProposal
6
+ from datahub.metadata.schema_classes import (
7
+ OwnerClass,
8
+ OwnershipClass,
9
+ OwnershipTypeClass,
10
+ )
11
+
12
+
13
+ class HasOwnershipPatch(MetadataPatchProposal):
14
+ def add_owner(self, owner: OwnerClass) -> Self:
15
+ """Add an owner to the entity.
16
+
17
+ Args:
18
+ owner: The Owner object to add.
19
+
20
+ Returns:
21
+ The patch builder instance.
22
+ """
23
+ self._add_patch(
24
+ OwnershipClass.ASPECT_NAME,
25
+ "add",
26
+ path=("owners", owner.owner, str(owner.type)),
27
+ value=owner,
28
+ )
29
+ return self
30
+
31
+ def remove_owner(
32
+ self, owner: str, owner_type: Optional[OwnershipTypeClass] = None
33
+ ) -> Self:
34
+ """Remove an owner from the entity.
35
+
36
+ If owner_type is not provided, the owner will be removed regardless of ownership type.
37
+
38
+ Args:
39
+ owner: The owner to remove.
40
+ owner_type: The ownership type of the owner (optional).
41
+
42
+ Returns:
43
+ The patch builder instance.
44
+ """
45
+ self._add_patch(
46
+ OwnershipClass.ASPECT_NAME,
47
+ "remove",
48
+ path=("owners", owner) + ((str(owner_type),) if owner_type else ()),
49
+ value=owner,
50
+ )
51
+ return self
52
+
53
+ def set_owners(self, owners: List[OwnerClass]) -> Self:
54
+ """Set the owners of the entity.
55
+
56
+ This will effectively replace all existing owners with the new list - it doesn't really patch things.
57
+
58
+ Args:
59
+ owners: The list of owners to set.
60
+
61
+ Returns:
62
+ The patch builder instance.
63
+ """
64
+ self._add_patch(
65
+ OwnershipClass.ASPECT_NAME, "add", path=("owners",), value=owners
66
+ )
67
+ return self
@@ -0,0 +1,72 @@
1
+ from typing import List, Union
2
+
3
+ from typing_extensions import Self
4
+
5
+ from datahub.emitter.mcp_patch_builder import MetadataPatchProposal
6
+ from datahub.metadata.schema_classes import (
7
+ StructuredPropertiesClass,
8
+ StructuredPropertyValueAssignmentClass,
9
+ )
10
+ from datahub.utilities.urns.structured_properties_urn import (
11
+ make_structured_property_urn,
12
+ )
13
+
14
+
15
+ class HasStructuredPropertiesPatch(MetadataPatchProposal):
16
+ def set_structured_property(
17
+ self, key: str, value: Union[str, float, List[Union[str, float]]]
18
+ ) -> Self:
19
+ """Add or update a structured property.
20
+
21
+ Args:
22
+ key: the name of the property (either bare or urn form)
23
+ value: the value of the property (for multi-valued properties, this can be a list)
24
+
25
+ Returns:
26
+ The patch builder instance.
27
+ """
28
+ self.remove_structured_property(key)
29
+ self.add_structured_property(key, value)
30
+ return self
31
+
32
+ def remove_structured_property(self, key: str) -> Self:
33
+ """Remove a structured property.
34
+
35
+ Args:
36
+ key: the name of the property (either bare or urn form)
37
+
38
+ Returns:
39
+ The patch builder instance.
40
+ """
41
+
42
+ self._add_patch(
43
+ StructuredPropertiesClass.ASPECT_NAME,
44
+ "remove",
45
+ path=("properties", make_structured_property_urn(key)),
46
+ value={},
47
+ )
48
+ return self
49
+
50
+ def add_structured_property(
51
+ self, key: str, value: Union[str, float, List[Union[str, float]]]
52
+ ) -> Self:
53
+ """Add a structured property.
54
+
55
+ Args:
56
+ key: the name of the property (either bare or urn form)
57
+ value: the value of the property (for multi-valued properties, this value will be appended to the list)
58
+
59
+ Returns:
60
+ The patch builder instance.
61
+ """
62
+
63
+ self._add_patch(
64
+ StructuredPropertiesClass.ASPECT_NAME,
65
+ "add",
66
+ path=("properties", make_structured_property_urn(key)),
67
+ value=StructuredPropertyValueAssignmentClass(
68
+ propertyUrn=make_structured_property_urn(key),
69
+ values=value if isinstance(value, list) else [value],
70
+ ),
71
+ )
72
+ return self
@@ -0,0 +1,42 @@
1
+ from typing import Union
2
+
3
+ from typing_extensions import Self
4
+
5
+ from datahub.emitter.mcp_patch_builder import MetadataPatchProposal
6
+ from datahub.metadata.schema_classes import (
7
+ GlobalTagsClass as GlobalTags,
8
+ TagAssociationClass as Tag,
9
+ )
10
+ from datahub.metadata.urns import TagUrn, Urn
11
+
12
+
13
+ class HasTagsPatch(MetadataPatchProposal):
14
+ def add_tag(self, tag: Tag) -> Self:
15
+ """Adds a tag to the entity.
16
+
17
+ Args:
18
+ tag: The Tag object representing the tag to be added.
19
+
20
+ Returns:
21
+ The patch builder instance.
22
+ """
23
+
24
+ # TODO: Make this support raw strings, in addition to Tag objects.
25
+ self._add_patch(
26
+ GlobalTags.ASPECT_NAME, "add", path=("tags", tag.tag), value=tag
27
+ )
28
+ return self
29
+
30
+ def remove_tag(self, tag: Union[str, Urn]) -> Self:
31
+ """Removes a tag from the entity.
32
+
33
+ Args:
34
+ tag: The tag to remove, specified as a string or Urn object.
35
+
36
+ Returns:
37
+ The patch builder instance.
38
+ """
39
+ if isinstance(tag, str) and not tag.startswith("urn:li:tag:"):
40
+ tag = TagUrn.create_from_id(tag)
41
+ self._add_patch(GlobalTags.ASPECT_NAME, "remove", path=("tags", tag), value={})
42
+ return self