smok/predicate/event.py
import pickle
import typing as tp
import uuid
from satella.coding import update_key_if_true
from satella.coding.structures import HashableIntEnum
from satella.json import JSONAble
from satella.time import time_as_int
class Color(HashableIntEnum):
"""
Event severity
"""
WHITE = 0 #: least severe event
YELLOW = 1 #: event of medium severity
RED = 2 #: most severe event
class Event(JSONAble):
"""
An object representing a single event in the SMOK system.
:ivar uuid: event UUID (str) after being synced with the server
:ivar provisional_uuid: UUID (str) assigned by the client after it's opening
:ivar started_on: timestamp of event beginning, in seconds (int)
:ivar ended_on: timestamp of event ending in seconds, or None if not ended (tp.Optional[int])
:ivar color: event color (:class:`~smok.predicate.Color`)
:ivar is_point: is the event a point one? (bool)
:ivar token: token (str)
:ivar group: event group (str)
:ivar message: human-readable message (str)
:ivar handled_by: user that handles this event (tp.Optional[str])
:ivar metadata: event metadata (tp.Dict[str, str])
"""
__slots__ = ('uuid', 'provisional_uuid', 'started_on', 'ended_on',
'color', 'is_point', 'token', 'group', 'message', 'handled_by',
'metadata')
def to_pickle(self) -> bytes:
"""
:return: pickled self
"""
return pickle.dumps(self, pickle.HIGHEST_PROTOCOL)
@classmethod
def from_pickle(cls, y: bytes) -> 'Event':
"""
Load an event from a pickle
:param y: pickled Event
:type y: bytes
:return: unpickled Event
:rtype: Event
"""
return pickle.loads(y)
def get_uuid(self) -> str:
if self.uuid:
return self.uuid
else:
return self.provisional_uuid
def uuid_matches(self, uuid_: str) -> bool:
return uuid_ == self.uuid or uuid_ == self.provisional_uuid
def __eq__(self, other: 'Event') -> bool:
return self.get_uuid() == other.get_uuid()
def __hash__(self) -> int:
return hash(self.get_uuid())
def __init__(self, uuid_: tp.Optional[str], started_on: tp.Optional[int],
ended_on: tp.Optional[int],
color: Color, is_point: bool, token: str, group: str, message: str,
handled_by: tp.Optional[str], metadata: tp.Dict[str, str]):
self.uuid = uuid_
if self.uuid is None:
self.provisional_uuid = uuid.uuid4().hex
else:
self.provisional_uuid = None
self.started_on = started_on or time_as_int()
self.ended_on = ended_on
self.color = color
self.is_point = is_point
self.token = token
self.group = group
self.message = message
self.handled_by = handled_by
self.metadata = metadata
def to_json(self) -> dict:
"""
Convert self to JSON representation
"""
dct = {
'started_on': self.started_on,
'color': self.color.value,
'alarm_type': 1 if self.is_point else 0,
'token': self.token,
'group': self.group,
'message': self.message,
'metadata': self.metadata
}
update_key_if_true(dct, 'uuid', self.uuid)
update_key_if_true(dct, 'handled_by', self.handled_by)
update_key_if_true(dct, 'ended_on', self.ended_on)
return dct
def is_closed(self) -> bool:
"""
:return: is given event closed?
"""
if self.is_point:
return True
return self.ended_on is not None
@classmethod
def from_json(cls, dct: dict) -> 'Event':
"""
Restore self from a JSON representation
"""
return Event(dct.get('uuid'), dct['started_on'], dct.get('ended_on'),
Color(dct['color']), dct['alarm_type'] == 1, dct['token'],
dct['group'], dct['message'], dct['metadata'])