<commit_before>"""
Provides the core event loop
"""
from collections import defaultdict

import signal
import copy
from spock.utils import pl_announce

import logging
logger = logging.getLogger('spock')

class EventCore:
	def __init__(self):
		self.kill_event = False
		self.event_handlers = defaultdict(list)
		signal.signal(signal.SIGINT, self.kill)
		signal.signal(signal.SIGTERM, self.kill)

	def event_loop(self):
		while not self.kill_event:
			self.emit('event_tick')
		logger.info('Event Kill called, shutting down')
		self.emit('kill')

	def reg_event_handler(self, event, handler):
		self.event_handlers[event].append(handler)

	def emit(self, event, data = None):
		to_remove = []
		for handler in self.event_handlers[event]:
			if handler(
				event,
				data.clone() if hasattr(data, 'clone') else copy.deepcopy(data)
			):
				to_remove.append(handler)
		for handler in to_remove:
			self.event_handlers[event].remove(handler)

	def kill(self, *args):
		self.kill_event = True

@pl_announce('Event')
class EventPlugin:
	def __init__(self, ploader, settings):
		ploader.provides('Event', EventCore())<commit_msg>Reverse event handler execution order to fix feedback loop issue<commit_after>"""
Provides the core event loop
"""
from collections import defaultdict

import signal
import copy
from spock.utils import pl_announce

import logging
logger = logging.getLogger('spock')

class EventCore:
	def __init__(self):
		self.kill_event = False
		self.event_handlers = defaultdict(list)
		signal.signal(signal.SIGINT, self.kill)
		signal.signal(signal.SIGTERM, self.kill)

	def event_loop(self):
		while not self.kill_event:
			self.emit('event_tick')
		logger.info('Event Kill called, shutting down')
		self.emit('kill')

	def reg_event_handler(self, event, handler):
		self.event_handlers[event].append(handler)

	def emit(self, event, data = None):
		to_remove = []
		# reversed, because handlers can register themselves
		# for the same event they handle, and the new handler
		# is appended to the end of the iterated handler list
		# and immediately run, so an infinite loop can be created
		for handler in reversed(self.event_handlers[event]):
			if handler(
				event,
				data.clone() if hasattr(data, 'clone') else copy.deepcopy(data)
			):
				to_remove.append(handler)
		for handler in to_remove:
			self.event_handlers[event].remove(handler)

	def kill(self, *args):
		self.kill_event = True

@pl_announce('Event')
class EventPlugin:
	def __init__(self, ploader, settings):
		ploader.provides('Event', EventCore())
{'fraction_non_alphanumeric': 0.10914105594956659, 'fraction_numerical': 0.0, 'mean_word_length': 4.904651162790698, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6510894', 'n_tokens_mistral': 883, 'n_tokens_neox': 802, 'n_words': 224}