Source code for pynenc.trigger.conditions.event
"""
Context for event-based conditions.
This module defines the EventContext class, which provides the necessary data
for evaluating event-based trigger conditions. It includes the event ID and
the associated payload.
"""
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Any, ClassVar
from pynenc.trigger.arguments import ArgumentFilter
from pynenc.trigger.conditions.base import ConditionContext, TriggerCondition
if TYPE_CHECKING:
from ...app import Pynenc
from pynenc.identifiers.task_id import TaskId
[docs]
@dataclass
class EventContext(ConditionContext):
"""
Context for event-based conditions.
Contains the necessary information about an event that occurred in the system,
allowing event-based conditions to determine if they should trigger.
"""
event_id: str # Unique identifier for this event instance
event_code: str # Type of event (used for matching conditions)
payload: dict[str, Any] = field(default_factory=dict) # Event data
@property
def context_id(self) -> str:
return f"event_{self.event_code}_{self.event_id}"
[docs]
def _to_json(self, app: "Pynenc") -> dict[str, Any]:
"""
Create a serializable representation of this event context.
:param app: Pynenc application instance
:return: Dictionary with serialized context data
"""
data: dict = {
"event_id": self.event_id,
"event_code": self.event_code,
}
# Serialize payload if present
if self.payload:
serialized_payload = {}
for key, value in self.payload.items():
serialized_payload[key] = app.client_data_store.serialize(value, False)
data["payload"] = serialized_payload
return data
[docs]
@classmethod
def _from_json(cls, data: dict[str, Any], app: "Pynenc") -> "EventContext":
"""
Create an EventContext from parsed JSON data.
:param data: Dictionary with context data
:param app: Pynenc application instance
:return: A new EventContext instance
"""
event_id = data.get("event_id")
event_code = data.get("event_code")
if not event_id or not event_code:
raise ValueError("Missing required fields in EventContext data")
payload_data = data.get("payload", {})
payload = {}
if payload_data:
for key, value in payload_data.items():
payload[key] = app.client_data_store.deserialize(value)
else:
payload = payload_data
return cls(event_id=event_id, event_code=event_code, payload=payload)
[docs]
class EventCondition(TriggerCondition[EventContext]):
"""
Condition based on system events.
Triggers a task when a specific event occurs, optionally filtered by event parameters.
"""
# Set the expected context type
context_type: ClassVar[type[EventContext]] = EventContext
def __init__(self, event_code: str, payload_filter: ArgumentFilter):
"""
Create an event-based trigger condition.
:param event_code: Type of event this condition matches
:param required_params: Optional parameters that must exist with matching values in the event
"""
self.event_code = event_code
self.payload_filter = payload_filter
@property
def condition_id(self) -> str:
"""
Generate a unique ID for this event condition.
:return: A string ID based on the event code and required parameters
"""
return f"event#{self.event_code}#{self.payload_filter.filter_id}"
[docs]
def get_source_task_ids(self) -> set["TaskId"]:
return set()
[docs]
def _to_json(self, app: "Pynenc") -> dict[str, Any]:
"""
Create a serializable representation of this condition.
:param app: Pynenc application instance for serializing complex arguments
:return: Dictionary with serialized condition data
"""
return {
"event_code": self.event_code,
"payload_filter": self.payload_filter.to_json(app),
}
[docs]
@classmethod
def _from_json(cls, data: dict[str, Any], app: "Pynenc") -> "EventCondition":
"""
Create an EventCondition from parsed JSON data.
:param data: Dictionary with condition data
:param app: Pynenc application instance for deserializing complex arguments
:return: A new EventCondition instance
:raises ValueError: If the data is invalid for this condition type
"""
event_code = data.get("event_code")
if not event_code:
raise ValueError("Missing required event_code in EventCondition data")
payload_filter = ArgumentFilter.from_json(data["payload_filter"], app)
return cls(event_code=event_code, payload_filter=payload_filter)
[docs]
def _is_satisfied_by(self, context: EventContext) -> bool:
"""
Check if this condition is satisfied by the given event context.
For an event condition to be satisfied:
1. The event code must match
2. All required parameters must exist in the payload with matching values
:param context: Event context to evaluate
:return: True if the condition is satisfied by the event
"""
# Check if event code matches
if context.event_code != self.event_code:
return False
# Check if all required parameters exist with matching values
return self.payload_filter.filter_arguments(context.payload)
[docs]
def affects_task(self, task_id: "TaskId") -> bool:
"""
Check if this condition is affected by a specific task.
Event conditions aren't directly tied to specific tasks.
:param task_id: ID of the task to check
:return: Always False for event conditions
"""
return False