Usage of the EventClass - demonstration on concrete class LogEvent

EventClass is merely an abstract class and serves as an interface for all EventClasses.

The LogEvent class extends an abstract base class and includes the following fields:

  • extra_data

  • metadata

  • original

LogEvent validates extra_data and checks whether all entries are in the DELIVERED state before setting itself to DELIVERED.

[2]:
import pickle

from tinycss2 import serialize

from logprep.ng.event.log_event import LogEvent
from logprep.ng.event.event_state import EventStateType
from logprep.ng.abc.event import Event


class DummyEvent(Event):
    __slots__ = Event.__slots__

Set LogEvent to delivered with SUCCESS

[3]:
child1 = DummyEvent({"c1": 1})
child2 = DummyEvent({"c2": 2})
child1.state.current_state = EventStateType.DELIVERED
child2.state.current_state = EventStateType.DELIVERED

log_event = LogEvent(
    data={"parent": "yes"},
    original=b"...",
    extra_data=[child1, child2],
)
log_event.state.current_state = EventStateType.STORED_IN_OUTPUT
log_event.state.next_state(success=True)

print(log_event.state.current_state)
delivered

Set LogEvent to delivered FAILING

[4]:
child1 = DummyEvent({"c1": 1})
child2 = DummyEvent({"c2": 2})
child1.state.current_state = EventStateType.DELIVERED
child2.state.current_state = EventStateType.PROCESSING

log_event = LogEvent(
    data={"parent": "yes"},
    original=b"...",
    extra_data=[child1, child2],
)
log_event.state.current_state = EventStateType.STORED_IN_OUTPUT
log_event.state.next_state(success=True)

print(log_event.state.current_state)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[4], line 12
      6 log_event = LogEvent(
      7     data={"parent": "yes"},
      8     original=b"...",
      9     extra_data=[child1, child2],
     10 )
     11 log_event.state.current_state = EventStateType.STORED_IN_OUTPUT
---> 12 log_event.state.next_state(success=True)
     14 print(log_event.state.current_state)

File ~/dev/bwi/Logprep/logprep/ng/event/log_event.py:69, in LogEvent._next_state_validation_helper(self, success)
     65 def _next_state_validation_helper(
     66     self, *, success: bool | None = None
     67 ) -> EventStateType | None:
     68     new_state: EventStateType = self._origin_state_next_state_fn(success=success)
---> 69     self._validate_state(new_state)
     70     return new_state

File ~/dev/bwi/Logprep/logprep/ng/event/log_event.py:75, in LogEvent._validate_state(self, state_type)
     73 if state_type == EventStateType.DELIVERED:
     74     if not all(e.state.current_state == EventStateType.DELIVERED for e in self.extra_data):
---> 75         raise ValueError(
     76             "Cannot assign DELIVERED state: not all extra_data events are DELIVERED."
     77         )

ValueError: Cannot assign DELIVERED state: not all extra_data events are DELIVERED.

Pickable / Hashable

The class and all its subclasses must be picklable and hashable.

  • Pickable: means that an object can be serialized and deserialized using Python’s pickle module, allowing it to be saved to disk or transferred between processes.

  • Hashable: means that an object can be used as a key in dictionaries, stored in sets or other hash-based containers, and used in equality comparisons with other objects. To be hashable, the object must have a stable hash() implementation and a consistent eq() behavior.

EQUALITY

[5]:
log_event = LogEvent(
    data={"log": "yes"},
    original=b"...",
)

other_equal_log_event = LogEvent(data={"log": "yes"}, original=b"...")

print(log_event==other_equal_log_event)
True
[6]:
other_not_equal_log_event = LogEvent(data={"log": "no"}, original=b"...")
print(log_event==other_not_equal_log_event)
False

PICKLABILITY

[7]:
import pickle
serialized = pickle.dumps(log_event)

print(serialized)
b'\x80\x04\x95\xb1\x01\x00\x00\x00\x00\x00\x00\x8c\x1alogprep.ng.event.log_event\x94\x8c\x08LogEvent\x94\x93\x94)\x81\x94N}\x94(\x8c\x08original\x94C\x03...\x94\x8c\nextra_data\x94]\x94\x8c\x08metadata\x94N\x8c\x06_state\x94\x8c\x1clogprep.ng.event.event_state\x94\x8c\nEventState\x94\x93\x94)\x81\x94}\x94(\x8c\rcurrent_state\x94h\x0b\x8c\x0eEventStateType\x94\x93\x94\x8c\treceiving\x94\x85\x94R\x94\x8c\nnext_state\x94\x8c\x08builtins\x94\x8c\x07getattr\x94\x93\x94h\x03\x8c\x1d_next_state_validation_helper\x94\x86\x94R\x94ub\x8c\x1b_origin_state_next_state_fn\x94\x8c\tfunctools\x94\x8c\x07partial\x94\x93\x94h\x0b\x8c\x15EventState.next_state\x94\x93\x94\x85\x94R\x94(h"h\x0e\x85\x94}\x94Nt\x94b\x8c\x04data\x94}\x94\x8c\x03log\x94\x8c\x03yes\x94s\x8c\x06errors\x94]\x94\x8c\x08warnings\x94]\x94u\x86\x94b.'
[8]:
copy_log_event = pickle.loads(serialized)
print("Comparison between original and deserialized object.\n Result (is equal):", log_event == copy_log_event, end="\n\n")

print(copy_log_event)
Comparison between original and deserialized object.
 Result (is equal): True

LogEvent(data={'log': 'yes'}, state=receiving)