44import typing
55from dataclasses import dataclass , field
66from enum import Enum
7- from typing import Any , Callable , Iterable , Type , TypeAlias , overload
8-
9- from dbt_score .models import Evaluable
7+ from typing import (
8+ Any ,
9+ Callable ,
10+ Iterable ,
11+ Type ,
12+ TypeAlias ,
13+ cast ,
14+ overload ,
15+ )
16+
17+ from dbt_score .models import Evaluable , Model , Source
1018from dbt_score .more_itertools import first_true
1119from dbt_score .rule_filter import RuleFilter
1220
@@ -55,7 +63,9 @@ class RuleViolation:
5563 message : str | None = None
5664
5765
58- RuleEvaluationType : TypeAlias = Callable [[Evaluable ], RuleViolation | None ]
66+ ModelRuleEvaluationType : TypeAlias = Callable [[Model ], RuleViolation | None ]
67+ SourceRuleEvaluationType : TypeAlias = Callable [[Source ], RuleViolation | None ]
68+ RuleEvaluationType : TypeAlias = ModelRuleEvaluationType | SourceRuleEvaluationType
5969
6070
6171class Rule :
@@ -66,7 +76,7 @@ class Rule:
6676 rule_filter_names : list [str ]
6777 rule_filters : frozenset [RuleFilter ] = frozenset ()
6878 default_config : typing .ClassVar [dict [str , Any ]] = {}
69- resource_type : typing .ClassVar [Evaluable ]
79+ resource_type : typing .ClassVar [type [ Evaluable ] ]
7080
7181 def __init__ (self , rule_config : RuleConfig | None = None ) -> None :
7282 """Initialize the rule."""
@@ -85,7 +95,7 @@ def __init_subclass__(cls, **kwargs) -> None: # type: ignore
8595 cls ._validate_rule_filters ()
8696
8797 @classmethod
88- def _validate_rule_filters (cls ):
98+ def _validate_rule_filters (cls ) -> None :
8999 for rule_filter in cls .rule_filters :
90100 if rule_filter .resource_type != cls .resource_type :
91101 raise TypeError (
@@ -111,7 +121,8 @@ def _introspect_resource_type(cls) -> Type[Evaluable]:
111121 "annotated Model or Source argument."
112122 )
113123
114- return resource_type_argument .annotation
124+ resource_type = cast (type [Evaluable ], resource_type_argument .annotation )
125+ return resource_type
115126
116127 def process_config (self , rule_config : RuleConfig ) -> None :
117128 """Process the rule config."""
@@ -178,7 +189,12 @@ def __hash__(self) -> int:
178189
179190
180191@overload
181- def rule (__func : RuleEvaluationType ) -> Type [Rule ]:
192+ def rule (__func : ModelRuleEvaluationType ) -> Type [Rule ]:
193+ ...
194+
195+
196+ @overload
197+ def rule (__func : SourceRuleEvaluationType ) -> Type [Rule ]:
182198 ...
183199
184200
@@ -214,9 +230,7 @@ def rule(
214230 rule_filters: Set of RuleFilter that filters the items that the rule applies to.
215231 """
216232
217- def decorator_rule (
218- func : RuleEvaluationType ,
219- ) -> Type [Rule ]:
233+ def decorator_rule (func : RuleEvaluationType ) -> Type [Rule ]:
220234 """Decorator function."""
221235 if func .__doc__ is None and description is None :
222236 raise AttributeError ("Rule must define `description` or `func.__doc__`." )
0 commit comments