sift_py.ingestion.rule.config

 1import sift_py.rule.config as rule_config
 2
 3RuleConfig = rule_config.RuleConfig
 4RuleAction = rule_config.RuleAction
 5RuleActionCreateDataReviewAnnotation = rule_config.RuleActionCreateDataReviewAnnotation
 6RuleActionCreatePhaseAnnotation = rule_config.RuleActionCreatePhaseAnnotation
 7RuleActionAnnotationKind = rule_config.RuleActionAnnotationKind
 8RuleActionKind = rule_config.RuleActionKind
 9RuleActionKindStrRep = rule_config.RuleActionKindStrRep
10ExpressionChannelReference = rule_config.ExpressionChannelReference
11ExpressionChannelReferenceChannelConfig = rule_config.ExpressionChannelReferenceChannelConfig
class RuleConfig(sift_py._internal.convert.json.AsJson):
 16class RuleConfig(AsJson):
 17    """
 18    Defines a rule to be used during ingestion. If a rule's expression validates to try, then
 19    a specific action will take place as specified by the `kind` attribute.
 20
 21    - `name`: Name of the rule.
 22    - `description`: Description of the rule.
 23    - `expression`: A CEL string expression that executes the `action` when evaluated to a truthy value.
 24    - `action`: The action to execute if the result of an `expression` evaluates to a truthy value.
 25    - `channel_references`: Reference to channel. If an expression is "$1 < 10", then "$1" is the reference and thus should the key in the dict.
 26    - `rule_client_key`: User defined unique string that uniquely identifies this rule.
 27    - `asset_names`: A list of asset names that this rule should be applied to. ONLY VALID if defining rules outside of a telemetry config.
 28    - `tag_names`: A list of asset names that this rule should be applied to. ONLY VALID if defining rules outside of a telemetry config.
 29    """
 30
 31    name: str
 32    description: str
 33    expression: str
 34    action: Optional[RuleAction]
 35    channel_references: List[ExpressionChannelReference]
 36    rule_client_key: Optional[str]
 37    asset_names: List[str]
 38
 39    def __init__(
 40        self,
 41        name: str,
 42        channel_references: List[
 43            Union[ExpressionChannelReference, ExpressionChannelReferenceChannelConfig]
 44        ],
 45        description: str = "",
 46        expression: str = "",
 47        action: Optional[RuleAction] = None,
 48        rule_client_key: Optional[str] = None,
 49        asset_names: Optional[List[str]] = None,
 50        tag_names: Optional[List[str]] = None,
 51        sub_expressions: Dict[str, Any] = {},
 52    ):
 53        self.channel_references = _channel_references_from_dicts(channel_references)
 54
 55        self.name = name
 56        self.asset_names = asset_names or []
 57        self.action = action
 58        self.rule_client_key = rule_client_key
 59        self.description = description
 60        self.expression = self.__class__.interpolate_sub_expressions(expression, sub_expressions)
 61
 62    def as_json(self) -> Any:
 63        """
 64        Produces the appropriate JSON structure that's suitable for the Rules API.
 65        """
 66
 67        hash_map: Dict[str, Union[List[ExpressionChannelReference], str, List[str], None]] = {
 68            "name": self.name,
 69            "description": self.description,
 70            "expression": self.expression,
 71        }
 72
 73        hash_map["expression_channel_references"] = self.channel_references
 74
 75        if isinstance(self.action, RuleActionCreateDataReviewAnnotation):
 76            hash_map["type"] = RuleActionAnnotationKind.REVIEW.value
 77            hash_map["assignee"] = self.action.assignee
 78
 79            if self.action.assignee is not None and len(self.action.assignee) > 0:
 80                hash_map["assignee"] = self.action.assignee
 81
 82            if self.action.tags is not None and len(self.action.tags) > 0:
 83                hash_map["tags"] = self.action.tags
 84
 85        elif isinstance(self.action, RuleActionCreatePhaseAnnotation):
 86            hash_map["type"] = RuleActionAnnotationKind.PHASE.value
 87
 88            if self.action.tags is not None and len(self.action.tags) > 0:
 89                hash_map["tags"] = self.action.tags
 90        else:
 91            kind = self.action.kind() if self.action else self.action
 92            raise TypeError(f"Unsupported rule action '{kind}'.")
 93
 94        return hash_map
 95
 96    @staticmethod
 97    def interpolate_sub_expressions(
 98        expression: str, sub_expressions: Optional[Dict[str, str]]
 99    ) -> str:
100        if sub_expressions:
101            for ref, expr in sub_expressions.items():
102                if ref not in expression:
103                    raise ValueError(f"Couldn't find '{ref}' in expression '{expression}'.")
104                if isinstance(expr, str):
105                    expression = expression.replace(ref, f'"{expr}"')
106                else:
107                    expression = expression.replace(ref, str(expr))
108
109        return expression

Defines a rule to be used during ingestion. If a rule's expression validates to try, then a specific action will take place as specified by the kind attribute.

  • name: Name of the rule.
  • description: Description of the rule.
  • expression: A CEL string expression that executes the action when evaluated to a truthy value.
  • action: The action to execute if the result of an expression evaluates to a truthy value.
  • channel_references: Reference to channel. If an expression is "$1 < 10", then "$1" is the reference and thus should the key in the dict.
  • rule_client_key: User defined unique string that uniquely identifies this rule.
  • asset_names: A list of asset names that this rule should be applied to. ONLY VALID if defining rules outside of a telemetry config.
  • tag_names: A list of asset names that this rule should be applied to. ONLY VALID if defining rules outside of a telemetry config.
RuleConfig( name: str, channel_references: List[Union[ExpressionChannelReference, ExpressionChannelReferenceChannelConfig]], description: str = '', expression: str = '', action: Union[RuleAction, NoneType] = None, rule_client_key: Union[str, NoneType] = None, asset_names: Union[List[str], NoneType] = None, tag_names: Union[List[str], NoneType] = None, sub_expressions: Dict[str, Any] = {})
39    def __init__(
40        self,
41        name: str,
42        channel_references: List[
43            Union[ExpressionChannelReference, ExpressionChannelReferenceChannelConfig]
44        ],
45        description: str = "",
46        expression: str = "",
47        action: Optional[RuleAction] = None,
48        rule_client_key: Optional[str] = None,
49        asset_names: Optional[List[str]] = None,
50        tag_names: Optional[List[str]] = None,
51        sub_expressions: Dict[str, Any] = {},
52    ):
53        self.channel_references = _channel_references_from_dicts(channel_references)
54
55        self.name = name
56        self.asset_names = asset_names or []
57        self.action = action
58        self.rule_client_key = rule_client_key
59        self.description = description
60        self.expression = self.__class__.interpolate_sub_expressions(expression, sub_expressions)
name: str
description: str
expression: str
action: Union[RuleAction, NoneType]
channel_references: List[ExpressionChannelReference]
rule_client_key: Union[str, NoneType]
asset_names: List[str]
def as_json(self) -> Any:
62    def as_json(self) -> Any:
63        """
64        Produces the appropriate JSON structure that's suitable for the Rules API.
65        """
66
67        hash_map: Dict[str, Union[List[ExpressionChannelReference], str, List[str], None]] = {
68            "name": self.name,
69            "description": self.description,
70            "expression": self.expression,
71        }
72
73        hash_map["expression_channel_references"] = self.channel_references
74
75        if isinstance(self.action, RuleActionCreateDataReviewAnnotation):
76            hash_map["type"] = RuleActionAnnotationKind.REVIEW.value
77            hash_map["assignee"] = self.action.assignee
78
79            if self.action.assignee is not None and len(self.action.assignee) > 0:
80                hash_map["assignee"] = self.action.assignee
81
82            if self.action.tags is not None and len(self.action.tags) > 0:
83                hash_map["tags"] = self.action.tags
84
85        elif isinstance(self.action, RuleActionCreatePhaseAnnotation):
86            hash_map["type"] = RuleActionAnnotationKind.PHASE.value
87
88            if self.action.tags is not None and len(self.action.tags) > 0:
89                hash_map["tags"] = self.action.tags
90        else:
91            kind = self.action.kind() if self.action else self.action
92            raise TypeError(f"Unsupported rule action '{kind}'.")
93
94        return hash_map

Produces the appropriate JSON structure that's suitable for the Rules API.

@staticmethod
def interpolate_sub_expressions(expression: str, sub_expressions: Union[Dict[str, str], NoneType]) -> str:
 96    @staticmethod
 97    def interpolate_sub_expressions(
 98        expression: str, sub_expressions: Optional[Dict[str, str]]
 99    ) -> str:
100        if sub_expressions:
101            for ref, expr in sub_expressions.items():
102                if ref not in expression:
103                    raise ValueError(f"Couldn't find '{ref}' in expression '{expression}'.")
104                if isinstance(expr, str):
105                    expression = expression.replace(ref, f'"{expr}"')
106                else:
107                    expression = expression.replace(ref, str(expr))
108
109        return expression
class RuleAction(abc.ABC):
112class RuleAction(ABC):
113    @abstractmethod
114    def kind(self) -> RuleActionKind:
115        pass

Helper class that provides a standard way to create an ABC using inheritance.

@abstractmethod
def kind(self) -> RuleActionKind:
113    @abstractmethod
114    def kind(self) -> RuleActionKind:
115        pass
class RuleActionCreateDataReviewAnnotation(sift_py.ingestion.rule.config.RuleAction):
118class RuleActionCreateDataReviewAnnotation(RuleAction):
119    """
120    Action to create a data-review annotation when a rule evaluates to a truthy value.
121
122    - `tags`: List of tag names to associate with the newly created data-review annotation.
123    - `assignee`: Email of user in organization to assign the newly created data-review annotation.
124    """
125
126    tags: Optional[List[str]]
127    assignee: Optional[str]
128
129    def __init__(self, assignee: Optional[str] = None, tags: Optional[List[str]] = None):
130        self.assignee = assignee
131        self.tags = tags
132
133    def kind(self) -> RuleActionKind:
134        return RuleActionKind.ANNOTATION

Action to create a data-review annotation when a rule evaluates to a truthy value.

  • tags: List of tag names to associate with the newly created data-review annotation.
  • assignee: Email of user in organization to assign the newly created data-review annotation.
RuleActionCreateDataReviewAnnotation( assignee: Union[str, NoneType] = None, tags: Union[List[str], NoneType] = None)
129    def __init__(self, assignee: Optional[str] = None, tags: Optional[List[str]] = None):
130        self.assignee = assignee
131        self.tags = tags
tags: Union[List[str], NoneType]
assignee: Union[str, NoneType]
def kind(self) -> RuleActionKind:
133    def kind(self) -> RuleActionKind:
134        return RuleActionKind.ANNOTATION
class RuleActionCreatePhaseAnnotation(sift_py.ingestion.rule.config.RuleAction):
137class RuleActionCreatePhaseAnnotation(RuleAction):
138    """
139    Action to create a phase annotation when a rule evaluates to a truthy value.
140
141    - `tags`: List of tag names to associate with the newly created data-review annotation.
142    """
143
144    tags: Optional[List[str]]
145
146    def __init__(self, tags: Optional[List[str]] = None):
147        self.tags = tags
148
149    def kind(self) -> RuleActionKind:
150        return RuleActionKind.ANNOTATION

Action to create a phase annotation when a rule evaluates to a truthy value.

  • tags: List of tag names to associate with the newly created data-review annotation.
RuleActionCreatePhaseAnnotation(tags: Union[List[str], NoneType] = None)
146    def __init__(self, tags: Optional[List[str]] = None):
147        self.tags = tags
tags: Union[List[str], NoneType]
def kind(self) -> RuleActionKind:
149    def kind(self) -> RuleActionKind:
150        return RuleActionKind.ANNOTATION
class RuleActionAnnotationKind(enum.Enum):
167class RuleActionAnnotationKind(Enum):
168    REVIEW = "review"
169    PHASE = "phase"
170
171    @classmethod
172    def from_annotation_type(cls, annotation_type: AnnotationType) -> "RuleActionAnnotationKind":
173        if annotation_type == AnnotationType.ANNOTATION_TYPE_PHASE:
174            return cls.PHASE
175        return cls.REVIEW
176
177    @classmethod
178    def from_str(cls, val: str) -> "RuleActionAnnotationKind":
179        if val == cls.REVIEW.value:
180            return cls.REVIEW
181        elif val == cls.PHASE.value:
182            return cls.PHASE
183        else:
184            raise ValueError(f"Argument '{val}' is not a valid annotation kind.")

An enumeration.

REVIEW = <RuleActionAnnotationKind.REVIEW: 'review'>
PHASE = <RuleActionAnnotationKind.PHASE: 'phase'>
@classmethod
def from_annotation_type( cls, annotation_type: <google.protobuf.internal.enum_type_wrapper.EnumTypeWrapper object>) -> RuleActionAnnotationKind:
171    @classmethod
172    def from_annotation_type(cls, annotation_type: AnnotationType) -> "RuleActionAnnotationKind":
173        if annotation_type == AnnotationType.ANNOTATION_TYPE_PHASE:
174            return cls.PHASE
175        return cls.REVIEW
@classmethod
def from_str(cls, val: str) -> RuleActionAnnotationKind:
177    @classmethod
178    def from_str(cls, val: str) -> "RuleActionAnnotationKind":
179        if val == cls.REVIEW.value:
180            return cls.REVIEW
181        elif val == cls.PHASE.value:
182            return cls.PHASE
183        else:
184            raise ValueError(f"Argument '{val}' is not a valid annotation kind.")
Inherited Members
enum.Enum
name
value
class RuleActionKind(enum.Enum):
153class RuleActionKind(Enum):
154    NOTIFICATION = ActionKind.NOTIFICATION
155    ANNOTATION = ActionKind.ANNOTATION
156
157    @classmethod
158    def from_str(cls, val: str) -> Optional["RuleActionKind"]:
159        if val == "ACTION_KIND_NOTIFICATION" or val == RuleActionKindStrRep.NOTIFICATION.value:
160            return cls.NOTIFICATION
161        elif val == "ACTION_KIND_ANNOTATION" or val == RuleActionKindStrRep.ANNOTATION.value:
162            return cls.ANNOTATION
163
164        return None

An enumeration.

NOTIFICATION = <RuleActionKind.NOTIFICATION: 1>
ANNOTATION = <RuleActionKind.ANNOTATION: 2>
@classmethod
def from_str(cls, val: str) -> Union[RuleActionKind, NoneType]:
157    @classmethod
158    def from_str(cls, val: str) -> Optional["RuleActionKind"]:
159        if val == "ACTION_KIND_NOTIFICATION" or val == RuleActionKindStrRep.NOTIFICATION.value:
160            return cls.NOTIFICATION
161        elif val == "ACTION_KIND_ANNOTATION" or val == RuleActionKindStrRep.ANNOTATION.value:
162            return cls.ANNOTATION
163
164        return None
Inherited Members
enum.Enum
name
value
class RuleActionKindStrRep(enum.Enum):
187class RuleActionKindStrRep(Enum):
188    NOTIFICATION = "notification"
189    ANNOTATION = "annotation"

An enumeration.

NOTIFICATION = <RuleActionKindStrRep.NOTIFICATION: 'notification'>
ANNOTATION = <RuleActionKindStrRep.ANNOTATION: 'annotation'>
Inherited Members
enum.Enum
name
value
class ExpressionChannelReference(typing_extensions.TypedDict):
192class ExpressionChannelReference(TypedDict):
193    """
194    `channel_reference`: The channel reference (e.g. '$1') used in the expression.
195    `channel_identifier`: The channel name.
196    """
197
198    channel_reference: str
199    channel_identifier: str

channel_reference: The channel reference (e.g. '$1') used in the expression. channel_identifier: The channel name.

channel_reference: str
channel_identifier: str
class ExpressionChannelReferenceChannelConfig(typing_extensions.TypedDict):
202class ExpressionChannelReferenceChannelConfig(TypedDict):
203    """
204    `channel_reference`: The channel reference (e.g. '$1') used in the expression.
205    `channel_config`: Instance of `sift_py.ingestion.channel.ChannelConfig`.
206    """
207
208    channel_reference: str
209    channel_config: ChannelConfig

channel_reference: The channel reference (e.g. '$1') used in the expression. channel_config: Instance of sift_py.ingestion.channel.ChannelConfig.

channel_reference: str