<commit_before>import logging, time, itertools
from ..config import config
from ..cnscom import svrcall_error
from .program import program
from .seqctrl import sequence_controller

###

L = logging.getLogger('proaster')

###

class program_roaster(object):
	'''
Program roaster is object that control all configured programs, their start/stop operations etc.
	'''

	def __init__(self):
		self.start_seq = None
		self.stop_seq = None
		self.restart_seq = None

		self.roaster = []
		for config_section in config.sections():
			if config_section.find('program:') != 0: continue
			sp = program(self.loop, config_section)
			self.roaster.append(sp)


	def filter_roaster_iter(self, pfilter=None):
		if pfilter is None:
			for p in self.roaster: yield p
			return

		filter_set = frozenset(pfilter)
		roaster_dict = dict((p.ident, p) for p in self.roaster)

		# Pass only known program names
		not_found = filter_set.difference(roaster_dict)
		if len(not_found) > 0: raise svrcall_error("Unknown/invalid program names: {0}".format(', '.join(not_found)))

		for ident, p in roaster_dict.iteritems():
			if ident in filter_set: yield p


	def start_program(self, pfilter=None, force=False):
		'''Start processes that are STOPPED and (forced) FATAL'''
		if self.start_seq is not None or self.stop_seq is not None or self.restart_seq is not None:
			raise svrcall_error("There is already start/stop sequence running - please wait and try again later.")

		l = self.filter_roaster_iter(pfilter)

		L.debug("Initializing start sequence")
		self.start_seq = sequence_controller()

		# If 'force' is used, include as programs in FATAL state
		if force: states = (program.state_enum.STOPPED,program.state_enum.FATAL)
		else: states = (program.state_enum.STOPPED,)

		for p in l:
			if p.state not in states: continue
			self.start_seq.add(p)		

		self.__startstop_pad_next(True)


	def stop_program(self, pfilter=None, force=True):
		'''Stop processes that are RUNNING and STARTING'''
		if force:
			self.start_seq = None
			self.restart_seq = None
			self.stop_seq = None

		else:
			if self.start_seq is not None or self.stop_seq is not None or self.restart_seq is not None:
				raise svrcall_error("There is already start/stop sequence running - please wait and try again later.")

		l = self.filter_roaster_iter(pfilter)

		L.debug("Initializing stop sequence")
		self.stop_seq = sequence_controller()

		for p in l:
			if p.state not in (program.state_enum.RUNNING, program.state_enum.STARTING): continue
			self.stop_seq.add(p)		

		self.__startstop_pad_next(False)<commit_msg>Adding commentary & fixing typo.<commit_after>import logging, time, itertools
from ..config import config
from ..cnscom import svrcall_error
from .program import program
from .seqctrl import sequence_controller

###

L = logging.getLogger('proaster')

###

class program_roaster(object):
	'''
Program roaster is object that control all configured programs, their start/stop operations etc.
	'''

	def __init__(self):
		self.start_seq = None
		self.stop_seq = None
		self.restart_seq = None

		self.roaster = []
		for config_section in config.sections():
			if config_section.find('program:') != 0: continue
			sp = program(self.loop, config_section)
			self.roaster.append(sp)


	def filter_roaster_iter(self, pfilter=None):
		if pfilter is None:
			for p in self.roaster: yield p
			return

		filter_set = frozenset(pfilter)
		roaster_dict = dict((p.ident, p) for p in self.roaster)

		# Pass only known program names
		not_found = filter_set.difference(roaster_dict)
		if len(not_found) > 0: raise svrcall_error("Unknown/invalid program names: {0}".format(', '.join(not_found)))

		for ident, p in roaster_dict.iteritems():
			if ident in filter_set: yield p


	def start_program(self, pfilter=None, force=False):
		'''Start processes that are STOPPED and (forced) FATAL'''
		if self.start_seq is not None or self.stop_seq is not None or self.restart_seq is not None:
			raise svrcall_error("There is already start/stop sequence running - please wait and try again later.")

		l = self.filter_roaster_iter(pfilter)

		L.debug("Initializing start sequence")
		self.start_seq = sequence_controller()

		# If 'force' is used, include as programs in FATAL state
		if force: states = (program.state_enum.STOPPED,program.state_enum.FATAL)
		else: states = (program.state_enum.STOPPED,)

		for p in l:
			if p.state not in states: continue
			self.start_seq.add(p)		

		self.__startstop_pad_next(True)


	def stop_program(self, pfilter=None, force=False):
		'''
		Stop processes that are RUNNING and STARTING
		@param force: If True then it interrupts any concurrently running start/stop sequence.
		'''
		if force:
			self.start_seq = None
			self.restart_seq = None
			self.stop_seq = None

		else:
			if self.start_seq is not None or self.stop_seq is not None or self.restart_seq is not None:
				raise svrcall_error("There is already start/stop sequence running - please wait and try again later.")

		l = self.filter_roaster_iter(pfilter)

		L.debug("Initializing stop sequence")
		self.stop_seq = sequence_controller()

		for p in l:
			if p.state not in (program.state_enum.RUNNING, program.state_enum.STARTING): continue
			self.stop_seq.add(p)		

		self.__startstop_pad_next(False)
{'fraction_non_alphanumeric': 0.09705042816365367, 'fraction_numerical': 0.001141769743101808, 'mean_word_length': 4.224652087475149, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, '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': '2068355', 'n_tokens_mistral': 1873, 'n_tokens_neox': 1676, 'n_words': 518}