|
1 | 1 | import datetime |
2 | 2 | import re |
3 | 3 | from dataclasses import dataclass, field |
| 4 | +from enum import Enum |
4 | 5 | from pathlib import Path |
5 | 6 | from typing import Any, Dict, List, Literal, Optional, Sequence, Union |
6 | 7 |
|
| 8 | +from typing_extensions import override |
| 9 | + |
7 | 10 | # trigger the PathEncoder |
8 | 11 | import dbt_common.helper_types # noqa:F401 |
9 | 12 | from dbt import deprecations |
@@ -580,15 +583,34 @@ class UnparsedMetricInput(dbtClassMixin): |
580 | 583 |
|
581 | 584 | @dataclass |
582 | 585 | class UnparsedConversionTypeParams(dbtClassMixin): |
583 | | - base_measure: Union[UnparsedMetricInputMeasure, str] |
584 | | - conversion_measure: Union[UnparsedMetricInputMeasure, str] |
585 | 586 | entity: str |
| 587 | + |
| 588 | + # *_measure params are for old-style YAML. |
| 589 | + base_measure: Optional[Union[UnparsedMetricInputMeasure, str]] = None |
| 590 | + conversion_measure: Optional[Union[UnparsedMetricInputMeasure, str]] = None |
| 591 | + # *_metric params are for v2-style metrics. |
| 592 | + base_metric: Optional[Union[UnparsedMetricInput, str]] = None |
| 593 | + conversion_metric: Optional[Union[UnparsedMetricInput, str]] = None |
| 594 | + |
586 | 595 | calculation: str = ( |
587 | 596 | ConversionCalculationType.CONVERSION_RATE.value |
588 | 597 | ) # ConversionCalculationType Enum |
589 | 598 | window: Optional[str] = None |
590 | 599 | constant_properties: Optional[List[ConstantPropertyInput]] = None |
591 | 600 |
|
| 601 | + @override |
| 602 | + @classmethod |
| 603 | + def validate(cls, data): |
| 604 | + super().validate(data) |
| 605 | + if data.get("base_measure") is None and data.get("base_metric") is None: |
| 606 | + raise ValidationError( |
| 607 | + "Conversion metrics must define a base_measure or base_metric parameter." |
| 608 | + ) |
| 609 | + if data.get("conversion_measure") is None and data.get("conversion_metric") is None: |
| 610 | + raise ValidationError( |
| 611 | + "Conversion metrics must define a conversion_measure or conversion_metric parameter." |
| 612 | + ) |
| 613 | + |
592 | 614 |
|
593 | 615 | @dataclass |
594 | 616 | class UnparsedCumulativeTypeParams(dbtClassMixin): |
@@ -674,30 +696,37 @@ class UnparsedMetricV2(UnparsedMetricBase): |
674 | 696 |
|
675 | 697 | join_to_timespine: Optional[bool] = None |
676 | 698 | fill_nulls_with: Optional[int] = None |
677 | | - expr: Optional[Union[str, int]] = None |
| 699 | + expr: Optional[Union[str, bool]] = None |
678 | 700 |
|
679 | 701 | non_additive_dimension: Optional[UnparsedNonAdditiveDimensionV2] = None |
680 | 702 | agg_time_dimension: Optional[str] = None |
681 | 703 |
|
682 | 704 | # For cumulative metrics |
683 | 705 | window: Optional[str] = None |
684 | 706 | grain_to_date: Optional[str] = None |
685 | | - period_agg: Optional[str] = None |
| 707 | + period_agg: str = PeriodAggregation.FIRST.value |
686 | 708 | input_metric: Optional[Union[str, Dict[str, Any]]] = None |
687 | 709 |
|
688 | 710 | # For ratio metrics |
689 | | - numerator: Optional[Union[str, Dict[str, Any]]] = None |
690 | | - denominator: Optional[Union[str, Dict[str, Any]]] = None |
| 711 | + numerator: Optional[Union[UnparsedMetricInput, str]] = None |
| 712 | + denominator: Optional[Union[UnparsedMetricInput, str]] = None |
691 | 713 |
|
692 | 714 | # For derived metrics |
693 | | - input_metrics: Optional[List[Dict[str, Any]]] = None |
| 715 | + input_metrics: Optional[List[Union[UnparsedMetricInput, str]]] = None |
694 | 716 |
|
695 | 717 | # For conversion metrics |
696 | 718 | entity: Optional[str] = None |
697 | 719 | calculation: Optional[str] = None |
698 | | - base_metric: Optional[Union[str, Dict[str, Any]]] = None |
699 | | - conversion_metric: Optional[Union[str, Dict[str, Any]]] = None |
700 | | - constant_properties: Optional[List[Dict[str, Any]]] = None |
| 720 | + base_metric: Optional[Union[UnparsedMetricInput, str]] = None |
| 721 | + conversion_metric: Optional[Union[UnparsedMetricInput, str]] = None |
| 722 | + constant_properties: Optional[List[ConstantPropertyInput]] = None |
| 723 | + |
| 724 | + @classmethod |
| 725 | + @override |
| 726 | + def validate(cls, data): |
| 727 | + super().validate(data) |
| 728 | + if data["type"] == "simple" and data.get("agg") is None: |
| 729 | + raise ValidationError("Simple metrics must have an agg param.") |
701 | 730 |
|
702 | 731 |
|
703 | 732 | @dataclass |
@@ -748,6 +777,11 @@ class UnparsedNonAdditiveDimension(dbtClassMixin): |
748 | 777 | window_groupings: List[str] = field(default_factory=list) |
749 | 778 |
|
750 | 779 |
|
| 780 | +class PercentileType(str, Enum): |
| 781 | + DISCRETE = "discrete" |
| 782 | + CONTINUOUS = "continuous" |
| 783 | + |
| 784 | + |
751 | 785 | @dataclass |
752 | 786 | class UnparsedMeasure(dbtClassMixin): |
753 | 787 | name: str |
|
0 commit comments