acryl-datahub-cloud 0.3.12rc1__py3-none-any.whl → 0.3.12rc3__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.

Files changed (70) hide show
  1. acryl_datahub_cloud/_codegen_config.json +1 -1
  2. acryl_datahub_cloud/datahub_forms_notifications/forms_notifications_source.py +524 -0
  3. acryl_datahub_cloud/datahub_forms_notifications/get_search_results_total.gql +14 -0
  4. acryl_datahub_cloud/datahub_forms_notifications/query.py +17 -0
  5. acryl_datahub_cloud/datahub_forms_notifications/scroll_forms_for_notification.gql +29 -0
  6. acryl_datahub_cloud/datahub_forms_notifications/send_form_notification_request.gql +5 -0
  7. acryl_datahub_cloud/datahub_usage_reporting/query_builder.py +48 -8
  8. acryl_datahub_cloud/datahub_usage_reporting/usage_feature_reporter.py +49 -40
  9. acryl_datahub_cloud/metadata/_urns/urn_defs.py +1842 -1786
  10. acryl_datahub_cloud/metadata/com/linkedin/pegasus2avro/application/__init__.py +19 -0
  11. acryl_datahub_cloud/metadata/com/linkedin/pegasus2avro/form/__init__.py +4 -0
  12. acryl_datahub_cloud/metadata/com/linkedin/pegasus2avro/notification/__init__.py +19 -0
  13. acryl_datahub_cloud/metadata/com/linkedin/pegasus2avro/settings/global/__init__.py +2 -0
  14. acryl_datahub_cloud/metadata/schema.avsc +24747 -23945
  15. acryl_datahub_cloud/metadata/schema_classes.py +1031 -631
  16. acryl_datahub_cloud/metadata/schemas/ApplicationKey.avsc +31 -0
  17. acryl_datahub_cloud/metadata/schemas/ApplicationProperties.avsc +72 -0
  18. acryl_datahub_cloud/metadata/schemas/Applications.avsc +38 -0
  19. acryl_datahub_cloud/metadata/schemas/AssertionAnalyticsRunEvent.avsc +31 -7
  20. acryl_datahub_cloud/metadata/schemas/AssertionInfo.avsc +27 -6
  21. acryl_datahub_cloud/metadata/schemas/AssertionRunEvent.avsc +31 -7
  22. acryl_datahub_cloud/metadata/schemas/AssertionsSummary.avsc +14 -0
  23. acryl_datahub_cloud/metadata/schemas/ChartKey.avsc +1 -0
  24. acryl_datahub_cloud/metadata/schemas/ConstraintInfo.avsc +12 -1
  25. acryl_datahub_cloud/metadata/schemas/ContainerKey.avsc +1 -0
  26. acryl_datahub_cloud/metadata/schemas/CorpGroupKey.avsc +2 -1
  27. acryl_datahub_cloud/metadata/schemas/CorpUserKey.avsc +2 -1
  28. acryl_datahub_cloud/metadata/schemas/DashboardKey.avsc +1 -0
  29. acryl_datahub_cloud/metadata/schemas/DataFlowKey.avsc +1 -0
  30. acryl_datahub_cloud/metadata/schemas/DataHubPolicyInfo.avsc +12 -1
  31. acryl_datahub_cloud/metadata/schemas/DataJobKey.avsc +1 -0
  32. acryl_datahub_cloud/metadata/schemas/DataProductKey.avsc +1 -0
  33. acryl_datahub_cloud/metadata/schemas/DataProductProperties.avsc +1 -1
  34. acryl_datahub_cloud/metadata/schemas/DatasetKey.avsc +1 -0
  35. acryl_datahub_cloud/metadata/schemas/FormAssignmentStatus.avsc +36 -0
  36. acryl_datahub_cloud/metadata/schemas/FormInfo.avsc +6 -0
  37. acryl_datahub_cloud/metadata/schemas/FormKey.avsc +2 -1
  38. acryl_datahub_cloud/metadata/schemas/FormNotifications.avsc +69 -0
  39. acryl_datahub_cloud/metadata/schemas/FormSettings.avsc +3 -0
  40. acryl_datahub_cloud/metadata/schemas/GlobalSettingsInfo.avsc +22 -0
  41. acryl_datahub_cloud/metadata/schemas/GlossaryTermKey.avsc +1 -0
  42. acryl_datahub_cloud/metadata/schemas/MLFeatureKey.avsc +1 -0
  43. acryl_datahub_cloud/metadata/schemas/MLFeatureTableKey.avsc +1 -0
  44. acryl_datahub_cloud/metadata/schemas/MLModelGroupKey.avsc +1 -0
  45. acryl_datahub_cloud/metadata/schemas/MLModelKey.avsc +1 -0
  46. acryl_datahub_cloud/metadata/schemas/MLPrimaryKeyKey.avsc +1 -0
  47. acryl_datahub_cloud/metadata/schemas/MetadataChangeEvent.avsc +12 -1
  48. acryl_datahub_cloud/metadata/schemas/MonitorInfo.avsc +27 -6
  49. acryl_datahub_cloud/metadata/schemas/NotebookKey.avsc +1 -0
  50. acryl_datahub_cloud/metadata/schemas/NotificationRequest.avsc +1 -0
  51. acryl_datahub_cloud/notifications/__init__.py +0 -0
  52. acryl_datahub_cloud/notifications/notification_recipient_builder.py +399 -0
  53. acryl_datahub_cloud/sdk/__init__.py +25 -0
  54. acryl_datahub_cloud/{_sdk_extras → sdk}/assertion.py +202 -45
  55. acryl_datahub_cloud/{_sdk_extras → sdk}/assertion_input.py +344 -83
  56. acryl_datahub_cloud/{_sdk_extras → sdk}/assertions_client.py +635 -199
  57. acryl_datahub_cloud/sdk/entities/__init__.py +0 -0
  58. acryl_datahub_cloud/{_sdk_extras → sdk}/entities/assertion.py +1 -1
  59. acryl_datahub_cloud/{_sdk_extras → sdk}/subscription_client.py +146 -33
  60. {acryl_datahub_cloud-0.3.12rc1.dist-info → acryl_datahub_cloud-0.3.12rc3.dist-info}/METADATA +48 -43
  61. {acryl_datahub_cloud-0.3.12rc1.dist-info → acryl_datahub_cloud-0.3.12rc3.dist-info}/RECORD +69 -54
  62. {acryl_datahub_cloud-0.3.12rc1.dist-info → acryl_datahub_cloud-0.3.12rc3.dist-info}/entry_points.txt +1 -0
  63. acryl_datahub_cloud/_sdk_extras/__init__.py +0 -19
  64. /acryl_datahub_cloud/{_sdk_extras/entities → datahub_forms_notifications}/__init__.py +0 -0
  65. /acryl_datahub_cloud/{_sdk_extras → sdk}/entities/monitor.py +0 -0
  66. /acryl_datahub_cloud/{_sdk_extras → sdk}/entities/subscription.py +0 -0
  67. /acryl_datahub_cloud/{_sdk_extras → sdk}/errors.py +0 -0
  68. /acryl_datahub_cloud/{_sdk_extras → sdk}/resolver_client.py +0 -0
  69. {acryl_datahub_cloud-0.3.12rc1.dist-info → acryl_datahub_cloud-0.3.12rc3.dist-info}/WHEEL +0 -0
  70. {acryl_datahub_cloud-0.3.12rc1.dist-info → acryl_datahub_cloud-0.3.12rc3.dist-info}/top_level.txt +0 -0
@@ -10,13 +10,14 @@ import logging
10
10
  from abc import ABC, abstractmethod
11
11
  from datetime import datetime
12
12
  from enum import Enum
13
- from typing import Any, Optional, Union
13
+ from typing import Optional, Union
14
14
 
15
15
  from typing_extensions import Self
16
16
 
17
- from acryl_datahub_cloud._sdk_extras.assertion_input import (
17
+ from acryl_datahub_cloud.sdk.assertion_input import (
18
18
  ASSERTION_MONITOR_DEFAULT_TRAINING_LOOKBACK_WINDOW_DAYS,
19
19
  DEFAULT_DETECTION_MECHANISM,
20
+ DEFAULT_SCHEDULE,
20
21
  DEFAULT_SENSITIVITY,
21
22
  AssertionIncidentBehavior,
22
23
  DetectionMechanism,
@@ -25,13 +26,15 @@ from acryl_datahub_cloud._sdk_extras.assertion_input import (
25
26
  InferenceSensitivity,
26
27
  _DetectionMechanismTypes,
27
28
  )
28
- from acryl_datahub_cloud._sdk_extras.entities.assertion import Assertion
29
- from acryl_datahub_cloud._sdk_extras.entities.monitor import Monitor
30
- from acryl_datahub_cloud._sdk_extras.errors import SDKNotYetSupportedError
29
+ from acryl_datahub_cloud.sdk.entities.assertion import Assertion
30
+ from acryl_datahub_cloud.sdk.entities.monitor import (
31
+ Monitor,
32
+ _get_nested_field_for_entity_with_default,
33
+ )
34
+ from acryl_datahub_cloud.sdk.errors import SDKNotYetSupportedError
31
35
  from datahub.emitter.mce_builder import parse_ts_millis
32
36
  from datahub.metadata import schema_classes as models
33
37
  from datahub.metadata.urns import AssertionUrn, CorpUserUrn, DatasetUrn, TagUrn
34
- from datahub.sdk.entity import Entity
35
38
 
36
39
  logger = logging.getLogger(__name__)
37
40
 
@@ -48,34 +51,33 @@ class AssertionMode(Enum):
48
51
  # PASSIVE = "PASSIVE" # Not supported in the user facing interface.
49
52
 
50
53
 
51
- def _get_nested_field_for_entity_with_default(
52
- entity: Entity,
53
- field_path: str,
54
- default: Any = None,
55
- ) -> Any:
54
+ class _HasSchedule:
56
55
  """
57
- Get a nested field from an Entity object, and warn and return default if not found.
58
-
59
- Args:
60
- entity: The entity to get the nested field from.
61
- field_path: The path to the nested field.
62
- default: The default value to return if the field is not found.
56
+ Mixin class that provides schedule functionality for assertions.
63
57
  """
64
- fields = field_path.split(".")
65
- current = entity
66
- last_valid_path = entity.entity_type_name()
67
-
68
- for field in fields:
69
- try:
70
- current = getattr(current, field)
71
- last_valid_path = f"{last_valid_path}.{field}"
72
- except AttributeError:
73
- logger.warning(
74
- f"{entity.entity_type_name().capitalize()} {entity.urn} does not have an `{last_valid_path}` field, defaulting to {default}"
75
- )
76
- return default
77
58
 
78
- return current
59
+ def __init__(self, schedule: models.CronScheduleClass) -> None:
60
+ self._schedule = schedule
61
+
62
+ @property
63
+ def schedule(self) -> models.CronScheduleClass:
64
+ return self._schedule
65
+
66
+ @staticmethod
67
+ def _get_schedule(monitor: Monitor) -> models.CronScheduleClass:
68
+ """Get the schedule from the monitor."""
69
+ assertion_evaluation_specs = _get_nested_field_for_entity_with_default(
70
+ monitor,
71
+ "info.assertionMonitor.assertions",
72
+ [],
73
+ )
74
+ if len(assertion_evaluation_specs) == 0:
75
+ return DEFAULT_SCHEDULE
76
+ assertion_evaluation_spec = assertion_evaluation_specs[0]
77
+ schedule = assertion_evaluation_spec.schedule
78
+ if schedule is None:
79
+ return DEFAULT_SCHEDULE
80
+ return schedule
79
81
 
80
82
 
81
83
  class _HasSmartFunctionality:
@@ -83,6 +85,11 @@ class _HasSmartFunctionality:
83
85
  Mixin class that provides smart functionality for assertions.
84
86
  """
85
87
 
88
+ _SUPPORTED_WITH_FILTER_ASSERTION_TYPES = (
89
+ models.FreshnessAssertionInfoClass,
90
+ models.VolumeAssertionInfoClass,
91
+ )
92
+
86
93
  def __init__(
87
94
  self,
88
95
  *,
@@ -204,17 +211,29 @@ class _HasSmartFunctionality:
204
211
  return _warn_and_return_default_detection_mechanism("parameters", default)
205
212
 
206
213
  # 2. Convert the raw detection mechanism to the SDK detection mechanism
207
- if (
208
- parameters.type
209
- == models.AssertionEvaluationParametersTypeClass.DATASET_FRESHNESS
210
- ):
211
- # TODO: Add support for other detection mechanisms when other assertion types are supported
212
- return _HasSmartFunctionality._get_freshness_detection_mechanism(
213
- assertion, parameters, default
214
- )
214
+ if parameters.type in [
215
+ models.AssertionEvaluationParametersTypeClass.DATASET_FRESHNESS,
216
+ models.AssertionEvaluationParametersTypeClass.DATASET_VOLUME,
217
+ ]:
218
+ if assertion.info is None:
219
+ return _warn_and_return_default_detection_mechanism("info", default)
220
+ if isinstance(assertion.info, models.VolumeAssertionInfoClass):
221
+ return _HasSmartFunctionality._get_volume_detection_mechanism(
222
+ assertion, parameters, default
223
+ )
224
+ elif isinstance(assertion.info, models.FreshnessAssertionInfoClass):
225
+ return _HasSmartFunctionality._get_freshness_detection_mechanism(
226
+ assertion, parameters, default
227
+ )
228
+ # TODO: Consider moving the detection mechanism logic to the assertion classes themselves e.g. _get_assertion_specific_detection_mechanism as an abstract method
229
+ # TODO: Add support here for other detection mechanisms when other assertion types are supported
230
+ else:
231
+ raise SDKNotYetSupportedError(
232
+ f"AssertionType {type(assertion.info).__name__}"
233
+ )
215
234
  else:
216
235
  raise SDKNotYetSupportedError(
217
- f"AssertionEvaluationParametersType {parameters.type}"
236
+ f"AssertionEvaluationParametersType {parameters.type} not supported"
218
237
  )
219
238
 
220
239
  @staticmethod
@@ -293,6 +312,33 @@ class _HasSmartFunctionality:
293
312
  else:
294
313
  raise SDKNotYetSupportedError(f"DatasetFreshnessSourceType {source_type}")
295
314
 
315
+ @staticmethod
316
+ def _get_volume_detection_mechanism(
317
+ assertion: Assertion,
318
+ parameters: models.AssertionEvaluationParametersClass,
319
+ default: Optional[_DetectionMechanismTypes] = DEFAULT_DETECTION_MECHANISM,
320
+ ) -> _DetectionMechanismTypes:
321
+ """Get the detection mechanism for volume assertions."""
322
+ if parameters.datasetVolumeParameters is None:
323
+ logger.warning(
324
+ f"Monitor does not have datasetVolumeParameters, defaulting detection mechanism to {DEFAULT_DETECTION_MECHANISM}"
325
+ )
326
+ if default is None:
327
+ return DEFAULT_DETECTION_MECHANISM
328
+ else:
329
+ return default
330
+
331
+ source_type = parameters.datasetVolumeParameters.sourceType
332
+ if source_type == models.DatasetVolumeSourceTypeClass.INFORMATION_SCHEMA:
333
+ return DetectionMechanism.INFORMATION_SCHEMA
334
+ elif source_type == models.DatasetVolumeSourceTypeClass.QUERY:
335
+ additional_filter = _HasSmartFunctionality._get_additional_filter(assertion)
336
+ return DetectionMechanism.QUERY(additional_filter=additional_filter)
337
+ elif source_type == models.DatasetVolumeSourceTypeClass.DATAHUB_DATASET_PROFILE:
338
+ return DetectionMechanism.DATASET_PROFILE
339
+ else:
340
+ raise SDKNotYetSupportedError(f"DatasetVolumeSourceType {source_type}")
341
+
296
342
  @staticmethod
297
343
  def _get_field_value_detection_mechanism(
298
344
  assertion: Assertion,
@@ -332,7 +378,10 @@ class _HasSmartFunctionality:
332
378
  )
333
379
  return None
334
380
  if (
335
- not isinstance(assertion.info, models.FreshnessAssertionInfoClass)
381
+ not isinstance(
382
+ assertion.info,
383
+ _HasSmartFunctionality._SUPPORTED_WITH_FILTER_ASSERTION_TYPES,
384
+ )
336
385
  or assertion.info.filter is None
337
386
  ):
338
387
  logger.warning(
@@ -500,19 +549,22 @@ class _AssertionPublic(ABC):
500
549
  return AssertionMode.INACTIVE
501
550
  return AssertionMode(monitor.info.status.mode)
502
551
 
552
+ @classmethod
503
553
  @abstractmethod
504
- def from_entities(
554
+ def _from_entities(
505
555
  cls,
506
556
  assertion: Assertion,
507
557
  monitor: Monitor,
508
558
  ) -> Self:
509
559
  """
510
560
  Create an assertion from the assertion and monitor entities.
561
+
562
+ Note: This is a private method since it is intended to be called internally by the client.
511
563
  """
512
564
  pass
513
565
 
514
566
 
515
- class SmartFreshnessAssertion(_HasSmartFunctionality, _AssertionPublic):
567
+ class SmartFreshnessAssertion(_HasSchedule, _HasSmartFunctionality, _AssertionPublic):
516
568
  """
517
569
  A class that represents a smart freshness assertion.
518
570
  """
@@ -524,6 +576,7 @@ class SmartFreshnessAssertion(_HasSmartFunctionality, _AssertionPublic):
524
576
  dataset_urn: DatasetUrn,
525
577
  display_name: str,
526
578
  mode: AssertionMode,
579
+ schedule: models.CronScheduleClass = DEFAULT_SCHEDULE,
527
580
  sensitivity: InferenceSensitivity = DEFAULT_SENSITIVITY,
528
581
  exclusion_windows: list[ExclusionWindowTypes],
529
582
  training_data_lookback_days: int = ASSERTION_MONITOR_DEFAULT_TRAINING_LOOKBACK_WINDOW_DAYS,
@@ -547,6 +600,105 @@ class SmartFreshnessAssertion(_HasSmartFunctionality, _AssertionPublic):
547
600
  dataset_urn: The urn of the dataset that the assertion is for.
548
601
  display_name: The display name of the assertion.
549
602
  mode: The mode of the assertion (active, inactive).
603
+ schedule: The schedule of the assertion.
604
+ sensitivity: The sensitivity of the assertion (low, medium, high).
605
+ exclusion_windows: The exclusion windows of the assertion.
606
+ training_data_lookback_days: The max number of days of data to use for training the assertion.
607
+ incident_behavior: Whether to raise or resolve an incident when the assertion fails / passes.
608
+ detection_mechanism: The detection mechanism of the assertion.
609
+ tags: The tags applied to the assertion.
610
+ created_by: The urn of the user that created the assertion.
611
+ created_at: The timestamp of when the assertion was created.
612
+ updated_by: The urn of the user that updated the assertion.
613
+ updated_at: The timestamp of when the assertion was updated.
614
+ """
615
+ # Initialize the mixins first
616
+ _HasSchedule.__init__(self, schedule=schedule)
617
+ _HasSmartFunctionality.__init__(
618
+ self,
619
+ sensitivity=sensitivity,
620
+ exclusion_windows=exclusion_windows,
621
+ training_data_lookback_days=training_data_lookback_days,
622
+ incident_behavior=incident_behavior,
623
+ detection_mechanism=detection_mechanism,
624
+ )
625
+ # Then initialize the parent class
626
+ _AssertionPublic.__init__(
627
+ self,
628
+ urn=urn,
629
+ dataset_urn=dataset_urn,
630
+ display_name=display_name,
631
+ mode=mode,
632
+ created_by=created_by,
633
+ created_at=created_at,
634
+ updated_by=updated_by,
635
+ updated_at=updated_at,
636
+ tags=tags,
637
+ )
638
+
639
+ @classmethod
640
+ def _from_entities(cls, assertion: Assertion, monitor: Monitor) -> Self:
641
+ """
642
+ Create a smart freshness assertion from the assertion and monitor entities.
643
+
644
+ Note: This is a private method since it is intended to be called internally by the client.
645
+ """
646
+ return cls(
647
+ urn=assertion.urn,
648
+ dataset_urn=assertion.dataset,
649
+ display_name=assertion.description or "",
650
+ mode=cls._get_mode(monitor),
651
+ schedule=cls._get_schedule(monitor),
652
+ sensitivity=cls._get_sensitivity(monitor),
653
+ exclusion_windows=cls._get_exclusion_windows(monitor),
654
+ training_data_lookback_days=cls._get_training_data_lookback_days(monitor),
655
+ incident_behavior=cls._get_incident_behavior(assertion),
656
+ detection_mechanism=cls._get_detection_mechanism(assertion, monitor),
657
+ created_by=cls._get_created_by(assertion),
658
+ created_at=cls._get_created_at(assertion),
659
+ updated_by=cls._get_updated_by(assertion),
660
+ updated_at=cls._get_updated_at(assertion),
661
+ tags=cls._get_tags(assertion),
662
+ )
663
+
664
+
665
+ class SmartVolumeAssertion(_HasSchedule, _HasSmartFunctionality, _AssertionPublic):
666
+ """
667
+ A class that represents a smart volume assertion.
668
+ """
669
+
670
+ def __init__(
671
+ self,
672
+ *,
673
+ urn: AssertionUrn,
674
+ dataset_urn: DatasetUrn,
675
+ display_name: str,
676
+ mode: AssertionMode,
677
+ schedule: models.CronScheduleClass,
678
+ sensitivity: InferenceSensitivity = DEFAULT_SENSITIVITY,
679
+ exclusion_windows: list[ExclusionWindowTypes],
680
+ training_data_lookback_days: int = ASSERTION_MONITOR_DEFAULT_TRAINING_LOOKBACK_WINDOW_DAYS,
681
+ incident_behavior: list[AssertionIncidentBehavior],
682
+ detection_mechanism: Optional[
683
+ _DetectionMechanismTypes
684
+ ] = DEFAULT_DETECTION_MECHANISM,
685
+ tags: list[TagUrn],
686
+ created_by: Optional[CorpUserUrn] = None,
687
+ created_at: Union[datetime, None] = None,
688
+ updated_by: Optional[CorpUserUrn] = None,
689
+ updated_at: Optional[datetime] = None,
690
+ ):
691
+ """
692
+ Initialize a smart volume assertion.
693
+
694
+ Note: Values can be accessed, but not set on the assertion object.
695
+ To update an assertion, use the `upsert_*` method.
696
+ Args:
697
+ urn: The urn of the assertion.
698
+ dataset_urn: The urn of the dataset that the assertion is for.
699
+ display_name: The display name of the assertion.
700
+ mode: The mode of the assertion (active, inactive).
701
+ schedule: The schedule of the assertion.
550
702
  sensitivity: The sensitivity of the assertion (low, medium, high).
551
703
  exclusion_windows: The exclusion windows of the assertion.
552
704
  training_data_lookback_days: The max number of days of data to use for training the assertion.
@@ -558,7 +710,8 @@ class SmartFreshnessAssertion(_HasSmartFunctionality, _AssertionPublic):
558
710
  updated_by: The urn of the user that updated the assertion.
559
711
  updated_at: The timestamp of when the assertion was updated.
560
712
  """
561
- # Initialize the mixin first
713
+ # Initialize the mixins first
714
+ _HasSchedule.__init__(self, schedule=schedule)
562
715
  _HasSmartFunctionality.__init__(
563
716
  self,
564
717
  sensitivity=sensitivity,
@@ -582,15 +735,18 @@ class SmartFreshnessAssertion(_HasSmartFunctionality, _AssertionPublic):
582
735
  )
583
736
 
584
737
  @classmethod
585
- def from_entities(cls, assertion: Assertion, monitor: Monitor) -> Self:
738
+ def _from_entities(cls, assertion: Assertion, monitor: Monitor) -> Self:
586
739
  """
587
740
  Create a smart freshness assertion from the assertion and monitor entities.
741
+
742
+ Note: This is a private method since it is intended to be called internally by the client.
588
743
  """
589
744
  return cls(
590
745
  urn=assertion.urn,
591
746
  dataset_urn=assertion.dataset,
592
747
  display_name=assertion.description or "",
593
748
  mode=cls._get_mode(monitor),
749
+ schedule=cls._get_schedule(monitor),
594
750
  sensitivity=cls._get_sensitivity(monitor),
595
751
  exclusion_windows=cls._get_exclusion_windows(monitor),
596
752
  training_data_lookback_days=cls._get_training_data_lookback_days(monitor),
@@ -606,5 +762,6 @@ class SmartFreshnessAssertion(_HasSmartFunctionality, _AssertionPublic):
606
762
 
607
763
  AssertionTypes = Union[
608
764
  SmartFreshnessAssertion,
765
+ SmartVolumeAssertion,
609
766
  # TODO: Add other assertion types here as we add them.
610
767
  ]