acryl-datahub-cloud 0.3.11rc0__py3-none-any.whl → 0.3.16.1rc0__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-cloud might be problematic. Click here for more details.
- acryl_datahub_cloud/_codegen_config.json +1 -1
- acryl_datahub_cloud/acryl_cs_issues/models.py +5 -3
- acryl_datahub_cloud/action_request/action_request_owner_source.py +36 -6
- acryl_datahub_cloud/datahub_forms_notifications/__init__.py +0 -0
- acryl_datahub_cloud/datahub_forms_notifications/forms_notifications_source.py +569 -0
- acryl_datahub_cloud/datahub_forms_notifications/get_feature_flag.gql +7 -0
- acryl_datahub_cloud/datahub_forms_notifications/get_search_results_total.gql +14 -0
- acryl_datahub_cloud/datahub_forms_notifications/query.py +17 -0
- acryl_datahub_cloud/datahub_forms_notifications/scroll_forms_for_notification.gql +29 -0
- acryl_datahub_cloud/datahub_forms_notifications/send_form_notification_request.gql +5 -0
- acryl_datahub_cloud/datahub_reporting/datahub_dataset.py +37 -13
- acryl_datahub_cloud/datahub_reporting/datahub_form_reporting.py +55 -24
- acryl_datahub_cloud/datahub_reporting/extract_graph.py +4 -3
- acryl_datahub_cloud/datahub_reporting/extract_sql.py +242 -51
- acryl_datahub_cloud/datahub_reporting/forms.py +1 -1
- acryl_datahub_cloud/datahub_reporting/forms_config.py +3 -2
- acryl_datahub_cloud/datahub_restore/source.py +3 -2
- acryl_datahub_cloud/datahub_usage_reporting/excluded.py +94 -0
- acryl_datahub_cloud/datahub_usage_reporting/query_builder.py +48 -8
- acryl_datahub_cloud/datahub_usage_reporting/usage_feature_reporter.py +518 -77
- acryl_datahub_cloud/elasticsearch/graph_service.py +76 -14
- acryl_datahub_cloud/graphql_utils.py +64 -0
- acryl_datahub_cloud/lineage_features/source.py +555 -49
- acryl_datahub_cloud/metadata/_urns/urn_defs.py +2296 -1900
- acryl_datahub_cloud/metadata/com/linkedin/pegasus2avro/actionworkflow/__init__.py +53 -0
- acryl_datahub_cloud/metadata/com/linkedin/pegasus2avro/anomaly/__init__.py +2 -0
- acryl_datahub_cloud/metadata/com/linkedin/pegasus2avro/application/__init__.py +19 -0
- acryl_datahub_cloud/metadata/com/linkedin/pegasus2avro/assertion/__init__.py +4 -2
- acryl_datahub_cloud/metadata/com/linkedin/pegasus2avro/common/__init__.py +6 -0
- acryl_datahub_cloud/metadata/com/linkedin/pegasus2avro/conversation/__init__.py +29 -0
- acryl_datahub_cloud/metadata/com/linkedin/pegasus2avro/event/notification/settings/__init__.py +2 -0
- acryl_datahub_cloud/metadata/com/linkedin/pegasus2avro/execution/__init__.py +2 -0
- acryl_datahub_cloud/metadata/com/linkedin/pegasus2avro/file/__init__.py +19 -0
- acryl_datahub_cloud/metadata/com/linkedin/pegasus2avro/form/__init__.py +8 -0
- acryl_datahub_cloud/metadata/com/linkedin/pegasus2avro/identity/__init__.py +8 -0
- acryl_datahub_cloud/metadata/com/linkedin/pegasus2avro/knowledge/__init__.py +33 -0
- acryl_datahub_cloud/metadata/com/linkedin/pegasus2avro/logical/__init__.py +15 -0
- acryl_datahub_cloud/metadata/com/linkedin/pegasus2avro/metadata/key/__init__.py +12 -0
- acryl_datahub_cloud/metadata/com/linkedin/pegasus2avro/metadata/search/features/__init__.py +2 -0
- acryl_datahub_cloud/metadata/com/linkedin/pegasus2avro/module/__init__.py +31 -0
- acryl_datahub_cloud/metadata/com/linkedin/pegasus2avro/notification/__init__.py +19 -0
- acryl_datahub_cloud/metadata/com/linkedin/pegasus2avro/platform/event/v1/__init__.py +4 -0
- acryl_datahub_cloud/metadata/com/linkedin/pegasus2avro/role/__init__.py +2 -0
- acryl_datahub_cloud/metadata/com/linkedin/pegasus2avro/settings/asset/__init__.py +19 -0
- acryl_datahub_cloud/metadata/com/linkedin/pegasus2avro/settings/global/__init__.py +28 -0
- acryl_datahub_cloud/metadata/com/linkedin/pegasus2avro/template/__init__.py +31 -0
- acryl_datahub_cloud/metadata/schema.avsc +25091 -20557
- acryl_datahub_cloud/metadata/schema_classes.py +29269 -23863
- acryl_datahub_cloud/metadata/schemas/ActionRequestInfo.avsc +235 -2
- acryl_datahub_cloud/metadata/schemas/ActionWorkflowInfo.avsc +683 -0
- acryl_datahub_cloud/metadata/schemas/ActionWorkflowKey.avsc +21 -0
- acryl_datahub_cloud/metadata/schemas/Actors.avsc +38 -1
- acryl_datahub_cloud/metadata/schemas/ApplicationKey.avsc +31 -0
- acryl_datahub_cloud/metadata/schemas/ApplicationProperties.avsc +75 -0
- acryl_datahub_cloud/metadata/schemas/Applications.avsc +38 -0
- acryl_datahub_cloud/metadata/schemas/AssertionAnalyticsRunEvent.avsc +353 -215
- acryl_datahub_cloud/metadata/schemas/AssertionInfo.avsc +147 -20
- acryl_datahub_cloud/metadata/schemas/AssertionKey.avsc +1 -1
- acryl_datahub_cloud/metadata/schemas/AssertionRunEvent.avsc +166 -21
- acryl_datahub_cloud/metadata/schemas/{AssertionSummary.avsc → AssertionRunSummary.avsc} +15 -2
- acryl_datahub_cloud/metadata/schemas/AssertionsSummary.avsc +54 -0
- acryl_datahub_cloud/metadata/schemas/AssetSettings.avsc +63 -0
- acryl_datahub_cloud/metadata/schemas/BusinessAttributeInfo.avsc +7 -3
- acryl_datahub_cloud/metadata/schemas/ChartInfo.avsc +20 -6
- acryl_datahub_cloud/metadata/schemas/ChartKey.avsc +1 -0
- acryl_datahub_cloud/metadata/schemas/ConstraintInfo.avsc +12 -1
- acryl_datahub_cloud/metadata/schemas/ContainerKey.avsc +1 -0
- acryl_datahub_cloud/metadata/schemas/ContainerProperties.avsc +16 -5
- acryl_datahub_cloud/metadata/schemas/CorpGroupEditableInfo.avsc +2 -1
- acryl_datahub_cloud/metadata/schemas/CorpGroupInfo.avsc +7 -3
- acryl_datahub_cloud/metadata/schemas/CorpGroupKey.avsc +2 -1
- acryl_datahub_cloud/metadata/schemas/CorpGroupSettings.avsc +127 -2
- acryl_datahub_cloud/metadata/schemas/CorpUserEditableInfo.avsc +1 -1
- acryl_datahub_cloud/metadata/schemas/CorpUserInfo.avsc +18 -2
- acryl_datahub_cloud/metadata/schemas/CorpUserInvitationStatus.avsc +106 -0
- acryl_datahub_cloud/metadata/schemas/CorpUserKey.avsc +4 -1
- acryl_datahub_cloud/metadata/schemas/CorpUserSettings.avsc +304 -2
- acryl_datahub_cloud/metadata/schemas/CorpUserUsageFeatures.avsc +86 -0
- acryl_datahub_cloud/metadata/schemas/DashboardInfo.avsc +11 -5
- acryl_datahub_cloud/metadata/schemas/DashboardKey.avsc +1 -0
- acryl_datahub_cloud/metadata/schemas/DataFlowInfo.avsc +15 -5
- acryl_datahub_cloud/metadata/schemas/DataFlowKey.avsc +1 -0
- acryl_datahub_cloud/metadata/schemas/DataHubAiConversationInfo.avsc +256 -0
- acryl_datahub_cloud/metadata/schemas/DataHubAiConversationKey.avsc +22 -0
- acryl_datahub_cloud/metadata/schemas/DataHubFileInfo.avsc +234 -0
- acryl_datahub_cloud/metadata/schemas/DataHubFileKey.avsc +22 -0
- acryl_datahub_cloud/metadata/schemas/DataHubIngestionSourceKey.avsc +2 -1
- acryl_datahub_cloud/metadata/schemas/DataHubPageModuleKey.avsc +21 -0
- acryl_datahub_cloud/metadata/schemas/DataHubPageModuleProperties.avsc +308 -0
- acryl_datahub_cloud/metadata/schemas/DataHubPageTemplateKey.avsc +21 -0
- acryl_datahub_cloud/metadata/schemas/DataHubPageTemplateProperties.avsc +251 -0
- acryl_datahub_cloud/metadata/schemas/DataHubPolicyInfo.avsc +12 -1
- acryl_datahub_cloud/metadata/schemas/DataJobInfo.avsc +13 -4
- acryl_datahub_cloud/metadata/schemas/DataJobInputOutput.avsc +8 -0
- acryl_datahub_cloud/metadata/schemas/DataJobKey.avsc +1 -0
- acryl_datahub_cloud/metadata/schemas/DataPlatformInfo.avsc +3 -1
- acryl_datahub_cloud/metadata/schemas/DataPlatformInstanceProperties.avsc +5 -2
- acryl_datahub_cloud/metadata/schemas/DataProcessKey.avsc +4 -0
- acryl_datahub_cloud/metadata/schemas/DataProductKey.avsc +2 -0
- acryl_datahub_cloud/metadata/schemas/DataProductProperties.avsc +6 -3
- acryl_datahub_cloud/metadata/schemas/DataTypeInfo.avsc +5 -0
- acryl_datahub_cloud/metadata/schemas/DatasetKey.avsc +10 -2
- acryl_datahub_cloud/metadata/schemas/DatasetProperties.avsc +12 -5
- acryl_datahub_cloud/metadata/schemas/DatasetUsageStatistics.avsc +8 -0
- acryl_datahub_cloud/metadata/schemas/DocumentInfo.avsc +407 -0
- acryl_datahub_cloud/metadata/schemas/DocumentKey.avsc +35 -0
- acryl_datahub_cloud/metadata/schemas/DocumentSettings.avsc +79 -0
- acryl_datahub_cloud/metadata/schemas/DomainKey.avsc +2 -0
- acryl_datahub_cloud/metadata/schemas/DomainProperties.avsc +7 -3
- acryl_datahub_cloud/metadata/schemas/EditableContainerProperties.avsc +2 -1
- acryl_datahub_cloud/metadata/schemas/EditableDashboardProperties.avsc +2 -1
- acryl_datahub_cloud/metadata/schemas/EditableDataFlowProperties.avsc +2 -1
- acryl_datahub_cloud/metadata/schemas/EditableDataJobProperties.avsc +2 -1
- acryl_datahub_cloud/metadata/schemas/EditableDatasetProperties.avsc +2 -1
- acryl_datahub_cloud/metadata/schemas/EditableERModelRelationshipProperties.avsc +2 -1
- acryl_datahub_cloud/metadata/schemas/EditableMLFeatureProperties.avsc +2 -1
- acryl_datahub_cloud/metadata/schemas/EditableMLFeatureTableProperties.avsc +2 -1
- acryl_datahub_cloud/metadata/schemas/EditableMLModelGroupProperties.avsc +2 -1
- acryl_datahub_cloud/metadata/schemas/EditableMLModelProperties.avsc +2 -1
- acryl_datahub_cloud/metadata/schemas/EditableNotebookProperties.avsc +2 -1
- acryl_datahub_cloud/metadata/schemas/EditableSchemaMetadata.avsc +4 -2
- acryl_datahub_cloud/metadata/schemas/EntityTypeInfo.avsc +5 -0
- acryl_datahub_cloud/metadata/schemas/ExecutionRequestArtifactsLocation.avsc +16 -0
- acryl_datahub_cloud/metadata/schemas/ExecutionRequestKey.avsc +2 -1
- acryl_datahub_cloud/metadata/schemas/FormAssignmentStatus.avsc +36 -0
- acryl_datahub_cloud/metadata/schemas/FormInfo.avsc +6 -0
- acryl_datahub_cloud/metadata/schemas/FormKey.avsc +3 -1
- acryl_datahub_cloud/metadata/schemas/FormNotifications.avsc +69 -0
- acryl_datahub_cloud/metadata/schemas/FormSettings.avsc +30 -0
- acryl_datahub_cloud/metadata/schemas/GlobalSettingsInfo.avsc +416 -0
- acryl_datahub_cloud/metadata/schemas/GlobalTags.avsc +2 -1
- acryl_datahub_cloud/metadata/schemas/GlossaryNodeInfo.avsc +3 -1
- acryl_datahub_cloud/metadata/schemas/GlossaryNodeKey.avsc +1 -0
- acryl_datahub_cloud/metadata/schemas/GlossaryTermInfo.avsc +3 -1
- acryl_datahub_cloud/metadata/schemas/GlossaryTermKey.avsc +2 -0
- acryl_datahub_cloud/metadata/schemas/IcebergWarehouseInfo.avsc +4 -0
- acryl_datahub_cloud/metadata/schemas/IncidentActivityEvent.avsc +3 -3
- acryl_datahub_cloud/metadata/schemas/IncidentInfo.avsc +3 -3
- acryl_datahub_cloud/metadata/schemas/InferredMetadata.avsc +71 -1
- acryl_datahub_cloud/metadata/schemas/InputFields.avsc +2 -1
- acryl_datahub_cloud/metadata/schemas/InviteToken.avsc +26 -0
- acryl_datahub_cloud/metadata/schemas/LineageFeatures.avsc +67 -42
- acryl_datahub_cloud/metadata/schemas/LogicalParent.avsc +145 -0
- acryl_datahub_cloud/metadata/schemas/MLFeatureKey.avsc +4 -1
- acryl_datahub_cloud/metadata/schemas/MLFeatureTableKey.avsc +4 -1
- acryl_datahub_cloud/metadata/schemas/MLModelDeploymentKey.avsc +7 -1
- acryl_datahub_cloud/metadata/schemas/MLModelGroupKey.avsc +9 -1
- acryl_datahub_cloud/metadata/schemas/MLModelKey.avsc +9 -1
- acryl_datahub_cloud/metadata/schemas/MLModelProperties.avsc +4 -2
- acryl_datahub_cloud/metadata/schemas/MLPrimaryKeyKey.avsc +4 -1
- acryl_datahub_cloud/metadata/schemas/MetadataChangeEvent.avsc +418 -97
- acryl_datahub_cloud/metadata/schemas/MetadataChangeLog.avsc +62 -44
- acryl_datahub_cloud/metadata/schemas/MetadataChangeProposal.avsc +61 -0
- acryl_datahub_cloud/metadata/schemas/MonitorAnomalyEvent.avsc +54 -9
- acryl_datahub_cloud/metadata/schemas/MonitorInfo.avsc +163 -23
- acryl_datahub_cloud/metadata/schemas/MonitorKey.avsc +9 -1
- acryl_datahub_cloud/metadata/schemas/MonitorSuiteInfo.avsc +128 -3
- acryl_datahub_cloud/metadata/schemas/NotebookInfo.avsc +5 -2
- acryl_datahub_cloud/metadata/schemas/NotebookKey.avsc +1 -0
- acryl_datahub_cloud/metadata/schemas/NotificationRequest.avsc +91 -4
- acryl_datahub_cloud/metadata/schemas/Operation.avsc +17 -0
- acryl_datahub_cloud/metadata/schemas/Ownership.avsc +71 -1
- acryl_datahub_cloud/metadata/schemas/QuerySubjects.avsc +2 -13
- acryl_datahub_cloud/metadata/schemas/RelationshipChangeEvent.avsc +215 -0
- acryl_datahub_cloud/metadata/schemas/RoleProperties.avsc +3 -1
- acryl_datahub_cloud/metadata/schemas/SchemaFieldInfo.avsc +3 -1
- acryl_datahub_cloud/metadata/schemas/SchemaFieldKey.avsc +3 -0
- acryl_datahub_cloud/metadata/schemas/SchemaMetadata.avsc +2 -1
- acryl_datahub_cloud/metadata/schemas/SemanticContent.avsc +123 -0
- acryl_datahub_cloud/metadata/schemas/StructuredProperties.avsc +69 -0
- acryl_datahub_cloud/metadata/schemas/StructuredPropertyDefinition.avsc +15 -4
- acryl_datahub_cloud/metadata/schemas/StructuredPropertySettings.avsc +9 -0
- acryl_datahub_cloud/metadata/schemas/SubscriptionInfo.avsc +136 -5
- acryl_datahub_cloud/metadata/schemas/SubscriptionKey.avsc +2 -1
- acryl_datahub_cloud/metadata/schemas/SystemMetadata.avsc +61 -0
- acryl_datahub_cloud/metadata/schemas/TagProperties.avsc +3 -1
- acryl_datahub_cloud/metadata/schemas/TestInfo.avsc +2 -1
- acryl_datahub_cloud/metadata/schemas/UpstreamLineage.avsc +9 -0
- acryl_datahub_cloud/metadata/schemas/UsageFeatures.avsc +10 -0
- acryl_datahub_cloud/notifications/__init__.py +0 -0
- acryl_datahub_cloud/notifications/notification_recipient_builder.py +399 -0
- acryl_datahub_cloud/sdk/__init__.py +69 -0
- acryl_datahub_cloud/sdk/assertion/__init__.py +58 -0
- acryl_datahub_cloud/sdk/assertion/assertion_base.py +779 -0
- acryl_datahub_cloud/sdk/assertion/column_metric_assertion.py +191 -0
- acryl_datahub_cloud/sdk/assertion/column_value_assertion.py +431 -0
- acryl_datahub_cloud/sdk/assertion/freshness_assertion.py +201 -0
- acryl_datahub_cloud/sdk/assertion/schema_assertion.py +268 -0
- acryl_datahub_cloud/sdk/assertion/smart_column_metric_assertion.py +212 -0
- acryl_datahub_cloud/sdk/assertion/smart_freshness_assertion.py +165 -0
- acryl_datahub_cloud/sdk/assertion/smart_sql_assertion.py +156 -0
- acryl_datahub_cloud/sdk/assertion/smart_volume_assertion.py +162 -0
- acryl_datahub_cloud/sdk/assertion/sql_assertion.py +273 -0
- acryl_datahub_cloud/sdk/assertion/types.py +20 -0
- acryl_datahub_cloud/sdk/assertion/volume_assertion.py +156 -0
- acryl_datahub_cloud/sdk/assertion_client/__init__.py +0 -0
- acryl_datahub_cloud/sdk/assertion_client/column_metric.py +545 -0
- acryl_datahub_cloud/sdk/assertion_client/column_value.py +617 -0
- acryl_datahub_cloud/sdk/assertion_client/freshness.py +371 -0
- acryl_datahub_cloud/sdk/assertion_client/helpers.py +166 -0
- acryl_datahub_cloud/sdk/assertion_client/schema.py +358 -0
- acryl_datahub_cloud/sdk/assertion_client/smart_column_metric.py +540 -0
- acryl_datahub_cloud/sdk/assertion_client/smart_freshness.py +373 -0
- acryl_datahub_cloud/sdk/assertion_client/smart_sql.py +411 -0
- acryl_datahub_cloud/sdk/assertion_client/smart_volume.py +380 -0
- acryl_datahub_cloud/sdk/assertion_client/sql.py +410 -0
- acryl_datahub_cloud/sdk/assertion_client/volume.py +446 -0
- acryl_datahub_cloud/sdk/assertion_input/__init__.py +0 -0
- acryl_datahub_cloud/sdk/assertion_input/assertion_input.py +1470 -0
- acryl_datahub_cloud/sdk/assertion_input/column_assertion_constants.py +114 -0
- acryl_datahub_cloud/sdk/assertion_input/column_assertion_utils.py +284 -0
- acryl_datahub_cloud/sdk/assertion_input/column_metric_assertion_input.py +759 -0
- acryl_datahub_cloud/sdk/assertion_input/column_metric_constants.py +109 -0
- acryl_datahub_cloud/sdk/assertion_input/column_value_assertion_input.py +810 -0
- acryl_datahub_cloud/sdk/assertion_input/freshness_assertion_input.py +305 -0
- acryl_datahub_cloud/sdk/assertion_input/schema_assertion_input.py +413 -0
- acryl_datahub_cloud/sdk/assertion_input/smart_column_metric_assertion_input.py +793 -0
- acryl_datahub_cloud/sdk/assertion_input/smart_freshness_assertion_input.py +218 -0
- acryl_datahub_cloud/sdk/assertion_input/smart_sql_assertion_input.py +181 -0
- acryl_datahub_cloud/sdk/assertion_input/smart_volume_assertion_input.py +189 -0
- acryl_datahub_cloud/sdk/assertion_input/sql_assertion_input.py +320 -0
- acryl_datahub_cloud/sdk/assertion_input/volume_assertion_input.py +635 -0
- acryl_datahub_cloud/sdk/assertions_client.py +1074 -0
- acryl_datahub_cloud/sdk/entities/__init__.py +0 -0
- acryl_datahub_cloud/sdk/entities/assertion.py +439 -0
- acryl_datahub_cloud/sdk/entities/monitor.py +291 -0
- acryl_datahub_cloud/sdk/entities/subscription.py +100 -0
- acryl_datahub_cloud/sdk/errors.py +34 -0
- acryl_datahub_cloud/sdk/resolver_client.py +42 -0
- acryl_datahub_cloud/sdk/subscription_client.py +737 -0
- {acryl_datahub_cloud-0.3.11rc0.dist-info → acryl_datahub_cloud-0.3.16.1rc0.dist-info}/METADATA +55 -49
- {acryl_datahub_cloud-0.3.11rc0.dist-info → acryl_datahub_cloud-0.3.16.1rc0.dist-info}/RECORD +235 -142
- {acryl_datahub_cloud-0.3.11rc0.dist-info → acryl_datahub_cloud-0.3.16.1rc0.dist-info}/WHEEL +1 -1
- {acryl_datahub_cloud-0.3.11rc0.dist-info → acryl_datahub_cloud-0.3.16.1rc0.dist-info}/entry_points.txt +1 -0
- acryl_datahub_cloud/_sdk_extras/__init__.py +0 -4
- acryl_datahub_cloud/_sdk_extras/assertion.py +0 -15
- acryl_datahub_cloud/_sdk_extras/assertions_client.py +0 -23
- {acryl_datahub_cloud-0.3.11rc0.dist-info → acryl_datahub_cloud-0.3.16.1rc0.dist-info}/top_level.txt +0 -0
|
File without changes
|
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
import uuid
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
from typing import (
|
|
4
|
+
Dict,
|
|
5
|
+
List,
|
|
6
|
+
Optional,
|
|
7
|
+
Tuple,
|
|
8
|
+
Type,
|
|
9
|
+
TypeAlias,
|
|
10
|
+
Union,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
from typing_extensions import (
|
|
14
|
+
Self,
|
|
15
|
+
assert_never,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
from acryl_datahub_cloud.sdk.errors import SDKNotYetSupportedError
|
|
19
|
+
from datahub.emitter.enum_helpers import get_enum_options
|
|
20
|
+
from datahub.emitter.mce_builder import make_ts_millis
|
|
21
|
+
from datahub.errors import SdkUsageError
|
|
22
|
+
from datahub.metadata import schema_classes as models
|
|
23
|
+
from datahub.metadata.urns import AssertionUrn, DatasetUrn
|
|
24
|
+
from datahub.sdk._shared import (
|
|
25
|
+
HasPlatformInstance,
|
|
26
|
+
HasTags,
|
|
27
|
+
TagsInputType,
|
|
28
|
+
)
|
|
29
|
+
from datahub.sdk.entity import Entity
|
|
30
|
+
from datahub.utilities.urns._urn_base import Urn
|
|
31
|
+
|
|
32
|
+
AssertionInfoInputType: TypeAlias = Union[
|
|
33
|
+
models.DatasetAssertionInfoClass,
|
|
34
|
+
models.FreshnessAssertionInfoClass,
|
|
35
|
+
models.VolumeAssertionInfoClass,
|
|
36
|
+
models.SqlAssertionInfoClass,
|
|
37
|
+
models.FieldAssertionInfoClass,
|
|
38
|
+
models.SchemaAssertionInfoClass,
|
|
39
|
+
# TODO: models.CustomAssertionInfoClass,
|
|
40
|
+
]
|
|
41
|
+
AssertionSourceInputType: TypeAlias = Union[
|
|
42
|
+
str, # assertion source type
|
|
43
|
+
models.AssertionSourceTypeClass,
|
|
44
|
+
models.AssertionSourceClass,
|
|
45
|
+
]
|
|
46
|
+
LastUpdatedInputType: TypeAlias = Union[
|
|
47
|
+
Tuple[int, str], # (timestamp, actor)
|
|
48
|
+
Tuple[datetime, str], # (datetime, actor)
|
|
49
|
+
models.AuditStampClass,
|
|
50
|
+
]
|
|
51
|
+
AssertionActionsInputType: TypeAlias = List[
|
|
52
|
+
Union[
|
|
53
|
+
str, # assertion action type: RAISE_INCIDENT, RESOLVE_INCIDENT
|
|
54
|
+
models.AssertionActionTypeClass,
|
|
55
|
+
models.AssertionActionClass,
|
|
56
|
+
]
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class Assertion(HasPlatformInstance, HasTags, Entity):
|
|
61
|
+
"""Represents an assertion in DataHub.
|
|
62
|
+
|
|
63
|
+
TODO: This is a placeholder for better documentation.
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
__slots__ = ()
|
|
67
|
+
|
|
68
|
+
@classmethod
|
|
69
|
+
def get_urn_type(cls) -> Type[AssertionUrn]:
|
|
70
|
+
"""Get the URN type for assertions.
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
The AssertionUrn class.
|
|
74
|
+
"""
|
|
75
|
+
return AssertionUrn
|
|
76
|
+
|
|
77
|
+
def __init__(
|
|
78
|
+
self,
|
|
79
|
+
*,
|
|
80
|
+
# Identity; it is automatically generated if not provided
|
|
81
|
+
id: Union[str, AssertionUrn, None] = None,
|
|
82
|
+
# Assertion info
|
|
83
|
+
info: AssertionInfoInputType,
|
|
84
|
+
description: Optional[str] = None,
|
|
85
|
+
external_url: Optional[str] = None,
|
|
86
|
+
custom_properties: Optional[Dict[str, str]] = None,
|
|
87
|
+
source: Optional[AssertionSourceInputType] = None,
|
|
88
|
+
last_updated: Optional[LastUpdatedInputType] = None,
|
|
89
|
+
# For assertions, platform+instance is not coupled to identity
|
|
90
|
+
platform: Optional[str] = None,
|
|
91
|
+
platform_instance: Optional[str] = None,
|
|
92
|
+
# Standard aspects
|
|
93
|
+
tags: Optional[TagsInputType] = None,
|
|
94
|
+
# Assertion actions
|
|
95
|
+
on_success: Optional[AssertionActionsInputType] = None,
|
|
96
|
+
on_failure: Optional[AssertionActionsInputType] = None,
|
|
97
|
+
):
|
|
98
|
+
super().__init__(urn=Assertion._ensure_id(id))
|
|
99
|
+
|
|
100
|
+
self._set_info(info)
|
|
101
|
+
if description is not None:
|
|
102
|
+
self.set_description(description)
|
|
103
|
+
if external_url is not None:
|
|
104
|
+
self.set_external_url(external_url)
|
|
105
|
+
if custom_properties is not None:
|
|
106
|
+
self.set_custom_properties(custom_properties)
|
|
107
|
+
if source is not None:
|
|
108
|
+
self._set_source(source)
|
|
109
|
+
if last_updated is not None:
|
|
110
|
+
self._set_last_updated(last_updated)
|
|
111
|
+
|
|
112
|
+
if platform is not None:
|
|
113
|
+
self._set_platform_instance(platform, platform_instance)
|
|
114
|
+
|
|
115
|
+
if tags is not None:
|
|
116
|
+
self.set_tags(tags)
|
|
117
|
+
|
|
118
|
+
if on_success is not None or on_failure is not None:
|
|
119
|
+
self._set_actions(on_success or [], on_failure or [])
|
|
120
|
+
|
|
121
|
+
@classmethod
|
|
122
|
+
def _new_from_graph(cls, urn: Urn, current_aspects: models.AspectBag) -> Self:
|
|
123
|
+
assert isinstance(urn, AssertionUrn)
|
|
124
|
+
assert "assertionInfo" in current_aspects, "AssertionInfo is required"
|
|
125
|
+
assertion_info = current_aspects["assertionInfo"]
|
|
126
|
+
info = cls._switch_assertion_info(assertion_info)
|
|
127
|
+
|
|
128
|
+
entity = cls(id=urn, info=info)
|
|
129
|
+
return entity._init_from_graph(current_aspects)
|
|
130
|
+
|
|
131
|
+
@property
|
|
132
|
+
def urn(self) -> AssertionUrn:
|
|
133
|
+
assert isinstance(self._urn, AssertionUrn)
|
|
134
|
+
return self._urn
|
|
135
|
+
|
|
136
|
+
@classmethod
|
|
137
|
+
def _ensure_id(cls, id: Union[str, AssertionUrn, None]) -> AssertionUrn:
|
|
138
|
+
if isinstance(id, str):
|
|
139
|
+
return AssertionUrn.from_string(id)
|
|
140
|
+
elif isinstance(id, AssertionUrn):
|
|
141
|
+
return id
|
|
142
|
+
elif id is None:
|
|
143
|
+
return AssertionUrn.from_string(f"urn:li:assertion:{uuid.uuid4()}")
|
|
144
|
+
else:
|
|
145
|
+
assert_never(id)
|
|
146
|
+
|
|
147
|
+
def _ensure_info(self) -> models.AssertionInfoClass:
|
|
148
|
+
# Compared with datasets, we don't have editable non-editable duality here
|
|
149
|
+
return self._setdefault_aspect(
|
|
150
|
+
models.AssertionInfoClass(
|
|
151
|
+
# TBC: just because we need to set one!
|
|
152
|
+
type=models.AssertionTypeClass.DATASET
|
|
153
|
+
)
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
def _ensure_actions(self) -> models.AssertionActionsClass:
|
|
157
|
+
return self._setdefault_aspect(
|
|
158
|
+
models.AssertionActionsClass(onSuccess=[], onFailure=[])
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
@property
|
|
162
|
+
def description(self) -> Optional[str]:
|
|
163
|
+
"""Get the description of the assertion.
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
The descripton if set, None otherwise.
|
|
167
|
+
"""
|
|
168
|
+
return self._ensure_info().description
|
|
169
|
+
|
|
170
|
+
def set_description(self, description: str) -> None:
|
|
171
|
+
"""Set the description of the assertion.
|
|
172
|
+
|
|
173
|
+
Args:
|
|
174
|
+
description: The description to set.
|
|
175
|
+
"""
|
|
176
|
+
self._ensure_info().description = description
|
|
177
|
+
|
|
178
|
+
def _set_info(self, assertion: AssertionInfoInputType) -> None:
|
|
179
|
+
info = self._ensure_info()
|
|
180
|
+
if isinstance(assertion, models.DatasetAssertionInfoClass):
|
|
181
|
+
info.datasetAssertion = assertion
|
|
182
|
+
info.type = models.AssertionTypeClass.DATASET
|
|
183
|
+
elif isinstance(assertion, models.FreshnessAssertionInfoClass):
|
|
184
|
+
info.freshnessAssertion = assertion
|
|
185
|
+
info.type = models.AssertionTypeClass.FRESHNESS
|
|
186
|
+
elif isinstance(assertion, models.VolumeAssertionInfoClass):
|
|
187
|
+
info.volumeAssertion = assertion
|
|
188
|
+
info.type = models.AssertionTypeClass.VOLUME
|
|
189
|
+
elif isinstance(assertion, models.SqlAssertionInfoClass):
|
|
190
|
+
info.sqlAssertion = assertion
|
|
191
|
+
info.type = models.AssertionTypeClass.SQL
|
|
192
|
+
elif isinstance(assertion, models.FieldAssertionInfoClass):
|
|
193
|
+
info.fieldAssertion = assertion
|
|
194
|
+
info.type = models.AssertionTypeClass.FIELD
|
|
195
|
+
elif isinstance(assertion, models.SchemaAssertionInfoClass):
|
|
196
|
+
info.schemaAssertion = assertion
|
|
197
|
+
info.type = models.AssertionTypeClass.DATA_SCHEMA
|
|
198
|
+
else:
|
|
199
|
+
assert_never(assertion)
|
|
200
|
+
|
|
201
|
+
@property
|
|
202
|
+
def info(self) -> AssertionInfoInputType:
|
|
203
|
+
"""Get the assertion info.
|
|
204
|
+
|
|
205
|
+
Returns:
|
|
206
|
+
The assertion info.
|
|
207
|
+
"""
|
|
208
|
+
info = self._ensure_info()
|
|
209
|
+
return Assertion._switch_assertion_info(info)
|
|
210
|
+
|
|
211
|
+
@property
|
|
212
|
+
def external_url(self) -> Optional[str]:
|
|
213
|
+
"""Get the external URL of the assertion.
|
|
214
|
+
|
|
215
|
+
Returns:
|
|
216
|
+
The external URL if set, None otherwise.
|
|
217
|
+
"""
|
|
218
|
+
return self._ensure_info().externalUrl
|
|
219
|
+
|
|
220
|
+
def set_external_url(self, external_url: str) -> None:
|
|
221
|
+
"""Set the external URL of the assertion.
|
|
222
|
+
|
|
223
|
+
Args:
|
|
224
|
+
external_url: The external URL to set.
|
|
225
|
+
"""
|
|
226
|
+
self._ensure_info().externalUrl = external_url
|
|
227
|
+
|
|
228
|
+
@property
|
|
229
|
+
def custom_properties(self) -> Dict[str, str]:
|
|
230
|
+
"""Get the custom properties of the assertion.
|
|
231
|
+
|
|
232
|
+
Returns:
|
|
233
|
+
Dictionary of custom properties.
|
|
234
|
+
"""
|
|
235
|
+
return self._ensure_info().customProperties
|
|
236
|
+
|
|
237
|
+
def set_custom_properties(self, custom_properties: Dict[str, str]) -> None:
|
|
238
|
+
"""Set the custom properties of the assertion.
|
|
239
|
+
|
|
240
|
+
Args:
|
|
241
|
+
custom_properties: Dictionary of custom properties to set.
|
|
242
|
+
"""
|
|
243
|
+
self._ensure_info().customProperties = custom_properties
|
|
244
|
+
|
|
245
|
+
@property
|
|
246
|
+
def source(self) -> Optional[models.AssertionSourceClass]:
|
|
247
|
+
"""Get the source of the assertion.
|
|
248
|
+
|
|
249
|
+
Returns:
|
|
250
|
+
The source if set, None otherwise.
|
|
251
|
+
"""
|
|
252
|
+
return self._ensure_info().source
|
|
253
|
+
|
|
254
|
+
def _set_source(self, source: AssertionSourceInputType) -> None:
|
|
255
|
+
"""Set the source of the assertion.
|
|
256
|
+
|
|
257
|
+
Args:
|
|
258
|
+
source: The source to set.
|
|
259
|
+
"""
|
|
260
|
+
info = self._ensure_info()
|
|
261
|
+
if isinstance(source, str):
|
|
262
|
+
# TBC: The model allows arbitrary strings, should we restrict this to AssertionSourceTypeClass enum values?
|
|
263
|
+
info.source = models.AssertionSourceClass(
|
|
264
|
+
type=source,
|
|
265
|
+
)
|
|
266
|
+
elif isinstance(source, models.AssertionSourceTypeClass):
|
|
267
|
+
info.source = models.AssertionSourceClass(
|
|
268
|
+
type=source,
|
|
269
|
+
)
|
|
270
|
+
elif isinstance(source, models.AssertionSourceClass):
|
|
271
|
+
info.source = source
|
|
272
|
+
else:
|
|
273
|
+
assert_never(source)
|
|
274
|
+
|
|
275
|
+
@property
|
|
276
|
+
def last_updated(self) -> Optional[models.AuditStampClass]:
|
|
277
|
+
"""Get the last updated audit event of the assertion.
|
|
278
|
+
|
|
279
|
+
Audit event includes the timestamp and the actor who made the change.
|
|
280
|
+
|
|
281
|
+
Returns:
|
|
282
|
+
The last updated audit event of the assertion, or None if not set.
|
|
283
|
+
"""
|
|
284
|
+
return self._ensure_info().lastUpdated
|
|
285
|
+
|
|
286
|
+
def _set_last_updated(self, last_updated: LastUpdatedInputType) -> None:
|
|
287
|
+
"""Set the last updated audit event, including the timestamp and the actor who made the change.
|
|
288
|
+
|
|
289
|
+
Args:
|
|
290
|
+
last_updated: A tuple containing the last updated timestamp and actor.
|
|
291
|
+
"""
|
|
292
|
+
info = self._ensure_info()
|
|
293
|
+
|
|
294
|
+
if isinstance(last_updated, tuple):
|
|
295
|
+
if len(last_updated) != 2:
|
|
296
|
+
raise SdkUsageError("Invalid length for last updated tuple")
|
|
297
|
+
|
|
298
|
+
tm, actor = last_updated
|
|
299
|
+
|
|
300
|
+
if not self._is_actor_urn(actor):
|
|
301
|
+
raise SdkUsageError(
|
|
302
|
+
"Invalid actor for last updated tuple, expected 'urn:li:corpuser:*' or 'urn:li:corpGroup:*'"
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
if isinstance(tm, datetime):
|
|
306
|
+
info.lastUpdated = models.AuditStampClass(make_ts_millis(tm), actor)
|
|
307
|
+
elif isinstance(tm, int):
|
|
308
|
+
info.lastUpdated = models.AuditStampClass(tm, actor)
|
|
309
|
+
else:
|
|
310
|
+
raise SdkUsageError(
|
|
311
|
+
"Invalid type for last updated tuple timestamp, expected int or datetime"
|
|
312
|
+
)
|
|
313
|
+
elif isinstance(last_updated, models.AuditStampClass):
|
|
314
|
+
if not self._is_actor_urn(last_updated.actor):
|
|
315
|
+
raise SdkUsageError(
|
|
316
|
+
"Invalid actor for last updated tuple, expected 'urn:li:corpuser:*' or 'urn:li:corpGroup:*'"
|
|
317
|
+
)
|
|
318
|
+
info.lastUpdated = last_updated
|
|
319
|
+
else:
|
|
320
|
+
assert_never(last_updated)
|
|
321
|
+
|
|
322
|
+
# TODO: is this defined somewhere else?
|
|
323
|
+
def _is_actor_urn(self, actor: str) -> bool:
|
|
324
|
+
"""Check if the actor is a valid URN.
|
|
325
|
+
|
|
326
|
+
Args:
|
|
327
|
+
actor: The actor to check.
|
|
328
|
+
|
|
329
|
+
Returns:
|
|
330
|
+
True if the actor is a valid URN, False otherwise.
|
|
331
|
+
"""
|
|
332
|
+
return actor.startswith("urn:li:corpuser:") or actor.startswith(
|
|
333
|
+
"urn:li:corpGroup:"
|
|
334
|
+
)
|
|
335
|
+
|
|
336
|
+
@property
|
|
337
|
+
def on_success(self) -> List[models.AssertionActionClass]:
|
|
338
|
+
"""Get the actions to perform on success.
|
|
339
|
+
|
|
340
|
+
Returns:
|
|
341
|
+
The actions to perform on success, it may be empty if not set.
|
|
342
|
+
"""
|
|
343
|
+
return self._ensure_actions().onSuccess
|
|
344
|
+
|
|
345
|
+
@property
|
|
346
|
+
def on_failure(self) -> List[models.AssertionActionClass]:
|
|
347
|
+
"""Get the actions to perform on failure.
|
|
348
|
+
|
|
349
|
+
Returns:
|
|
350
|
+
The actions to perform on failure, it may be empty if not set.
|
|
351
|
+
"""
|
|
352
|
+
return self._ensure_actions().onFailure
|
|
353
|
+
|
|
354
|
+
def _set_actions(
|
|
355
|
+
self,
|
|
356
|
+
on_success: AssertionActionsInputType,
|
|
357
|
+
on_failure: AssertionActionsInputType,
|
|
358
|
+
) -> None:
|
|
359
|
+
"""Set the actions to perform on success or failure.
|
|
360
|
+
|
|
361
|
+
Args:
|
|
362
|
+
on_success: The actions to perform on success.
|
|
363
|
+
on_failure: The actions to perform on failure.
|
|
364
|
+
"""
|
|
365
|
+
for action in on_success + on_failure:
|
|
366
|
+
if isinstance(action, str) and action not in [
|
|
367
|
+
models.AssertionActionTypeClass.RAISE_INCIDENT,
|
|
368
|
+
models.AssertionActionTypeClass.RESOLVE_INCIDENT,
|
|
369
|
+
]:
|
|
370
|
+
raise SdkUsageError(
|
|
371
|
+
f"Invalid action type {str} for on_success or on_failure actions, expected valid str or AssertionActionTypeClass"
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
actions = self._ensure_actions()
|
|
375
|
+
actions.onSuccess = [
|
|
376
|
+
action
|
|
377
|
+
if isinstance(action, models.AssertionActionClass)
|
|
378
|
+
else models.AssertionActionClass(type=action)
|
|
379
|
+
for action in on_success
|
|
380
|
+
]
|
|
381
|
+
actions.onFailure = [
|
|
382
|
+
action
|
|
383
|
+
if isinstance(action, models.AssertionActionClass)
|
|
384
|
+
else models.AssertionActionClass(type=action)
|
|
385
|
+
for action in on_failure
|
|
386
|
+
]
|
|
387
|
+
|
|
388
|
+
@property
|
|
389
|
+
def dataset(self) -> DatasetUrn:
|
|
390
|
+
"""Get the dataset URN associated with the assertion.
|
|
391
|
+
|
|
392
|
+
Returns:
|
|
393
|
+
The dataset URN.
|
|
394
|
+
"""
|
|
395
|
+
info = self._ensure_info()
|
|
396
|
+
assertion_info = Assertion._switch_assertion_info(info)
|
|
397
|
+
|
|
398
|
+
dataset_str = (
|
|
399
|
+
assertion_info.dataset
|
|
400
|
+
if isinstance(assertion_info, models.DatasetAssertionInfoClass)
|
|
401
|
+
else assertion_info.entity
|
|
402
|
+
)
|
|
403
|
+
return DatasetUrn.from_string(dataset_str)
|
|
404
|
+
|
|
405
|
+
@classmethod
|
|
406
|
+
def _switch_assertion_info(
|
|
407
|
+
cls,
|
|
408
|
+
assertion_info: models.AssertionInfoClass,
|
|
409
|
+
) -> Union[
|
|
410
|
+
models.DatasetAssertionInfoClass,
|
|
411
|
+
models.FreshnessAssertionInfoClass,
|
|
412
|
+
models.VolumeAssertionInfoClass,
|
|
413
|
+
models.SqlAssertionInfoClass,
|
|
414
|
+
models.FieldAssertionInfoClass,
|
|
415
|
+
models.SchemaAssertionInfoClass,
|
|
416
|
+
]:
|
|
417
|
+
if assertion_info.type not in get_enum_options(models.AssertionTypeClass):
|
|
418
|
+
raise SDKNotYetSupportedError(f"Assertion type: {assertion_info.type}")
|
|
419
|
+
|
|
420
|
+
if assertion_info.type == models.AssertionTypeClass.DATASET:
|
|
421
|
+
assert assertion_info.datasetAssertion is not None
|
|
422
|
+
return assertion_info.datasetAssertion
|
|
423
|
+
elif assertion_info.type == models.AssertionTypeClass.FRESHNESS:
|
|
424
|
+
assert assertion_info.freshnessAssertion is not None
|
|
425
|
+
return assertion_info.freshnessAssertion
|
|
426
|
+
elif assertion_info.type == models.AssertionTypeClass.VOLUME:
|
|
427
|
+
assert assertion_info.volumeAssertion is not None
|
|
428
|
+
return assertion_info.volumeAssertion
|
|
429
|
+
elif assertion_info.type == models.AssertionTypeClass.SQL:
|
|
430
|
+
assert assertion_info.sqlAssertion is not None
|
|
431
|
+
return assertion_info.sqlAssertion
|
|
432
|
+
elif assertion_info.type == models.AssertionTypeClass.FIELD:
|
|
433
|
+
assert assertion_info.fieldAssertion is not None
|
|
434
|
+
return assertion_info.fieldAssertion
|
|
435
|
+
elif assertion_info.type == models.AssertionTypeClass.DATA_SCHEMA:
|
|
436
|
+
assert assertion_info.schemaAssertion is not None
|
|
437
|
+
return assertion_info.schemaAssertion
|
|
438
|
+
else:
|
|
439
|
+
raise AssertionError("Unreachable code, all cases should be handled above")
|