def test_scheduler_listener(self): config = SchedulerConfiguration() self.assertIsNotNone(config) scheduler = ProgramyScheduler(self._test_client, config) self.assertIsNotNone(scheduler) scheduler_listener(JobExecutionEvent(apscheduler.events.EVENT_SCHEDULER_STARTED, 1, None, None))
def test_scheduler_listener_unknown_event(self): config = SchedulerConfiguration() self.assertIsNotNone(config) scheduler = ProgramyScheduler(self._test_client, config) self.assertIsNotNone(scheduler) scheduler_listener(JobExecutionEvent(-1, 1, None, None))
def test_create_scheduler_no_blocking(self): config = SchedulerConfiguration() config._blocking = False self.assertIsNotNone(config) scheduler = ProgramyScheduler(self._test_client, config) self.assertIsNotNone(scheduler) self.assertIsInstance(scheduler._scheduler, BackgroundScheduler)
def test_init_custom_config(self): config = SchedulerConfiguration() config._debug_level = logging.DEBUG config._add_listeners = True self.assertIsNotNone(config) scheduler = ProgramyScheduler(self._test_client, config) self.assertIsNotNone(scheduler) self.assertIsInstance(scheduler._scheduler, BackgroundScheduler)
def test_create_scheduler_blocking_with_jobstore(self): config = SchedulerConfiguration() config._blocking = True config._jobstore = SchedulerJobStoreConfiguration() config._jobstore._name = "sqlalchemy" config._jobstore._storage = SchedulerSqlAlchemyJobStoreConfiguration() config._jobstore._storage._url = "sqlite:///programy.sqlite" scheduler = ProgramyScheduler(self._test_client, config) self.assertIsNotNone(scheduler) self.assertIsInstance(scheduler._scheduler, BlockingScheduler)
def test_get_event_str_job_execution_event(self): scheduled_run_time = datetime.strptime("10/04/18 19:02", "%d/%m/%y %H:%M") event = JobExecutionEvent("code", "job_id", "jobstore", scheduled_run_time, retval=1) message = ProgramyScheduler.get_event_str(event) self.assertIsNotNone(message) self.assertEqual( "JobExecutionEvent [code] [job_id] [jobstore] [2018-04-10 19:02:00] [1]", message)
def test_scheduled_srai(self): client = MockClient() scheduler1 = ProgramyScheduler(client, SchedulerConfiguration()) scheduler1.scheduled("user1", "client1", "SRAI", "Hello") self.assertEquals("Mock Response", client._response)
def test_scheduled_text(self): client = MockClient() scheduler1 = ProgramyScheduler(client, SchedulerConfiguration()) scheduler1.scheduled("user1", "client1", "TEXT", "Hello") self.assertEquals("Hello", client._response)
def test_get_event_str_scheduler_event(self): event = SchedulerEvent("code", "alias") message = ProgramyScheduler.get_event_str(event) self.assertIsNotNone(message) self.assertEquals("SchedulerEvent [code] [alias]", message)
def test_get_event_unknown(self): event = unittest.mock.Mock() message = ProgramyScheduler.get_event_str(event) self.assertIsNone(message)
def test_get_event_str_job_event(self): event = JobEvent("code", "id", "jobstore") message = ProgramyScheduler.get_event_str(event) self.assertIsNotNone(message) self.assertEqual("JobEvent [code] [id] [jobstore] [None]", message)
def test_listener_event_none_event(self): ProgramyScheduler.listener_event("Mock Event")
def test_create_scheduler_no_config(self): scheduler = ProgramyScheduler(self._test_client, None) self.assertIsNotNone(scheduler) self.assertIsNone(scheduler._scheduler)
def test_init_default_config(self): config = SchedulerConfiguration() self.assertIsNotNone(config) scheduler = ProgramyScheduler(self._test_client, config) self.assertIsNotNone(scheduler) self.assertIsInstance(scheduler._scheduler, BackgroundScheduler)
def load_scheduler(self): if self.configuration.client_configuration.scheduler is not None: self._scheduler = ProgramyScheduler( self, self.configuration.client_configuration.scheduler) self._scheduler.start()
class BotClient(ResponseLogger): def __init__(self, id, argument_parser=None): self._id = id self._arguments = self.parse_arguments(argument_parser=argument_parser) self.initiate_logging(self.arguments) self._configuration = None self.load_configuration(self.arguments) self.parse_configuration() self._bot_factory = BotFactory(self, self.configuration.client_configuration) self._license_keys = LicenseKeys() self.load_license_keys() self.get_license_keys() self._scheduler = None self.load_scheduler() self._renderer = self.load_renderer() def ylogger_type(self): return "client" @property def configuration(self): return self._configuration @property def id(self): return self._id @property def arguments(self): return self._arguments @property def license_keys(self): return self._license_keys @property def scheduler(self): return self._scheduler @property def bot_factory(self): return self._bot_factory @property def renderer(self): return self._renderer def get_description(self): raise NotImplementedError( "You must override this and return a client description") def add_client_arguments(self, parser=None): # Nothing to add return def parse_configuration(self): # Nothing to add return def parse_args(self, arguments, parsed_args): # Nothing to add return def parse_arguments(self, argument_parser): client_args = CommandLineClientArguments(self, parser=argument_parser) client_args.parse_args(self) return client_args def load_license_keys(self): if self.configuration is not None: if self.configuration.client_configuration.license_keys is not None: self._license_keys.load_license_key_file( self.configuration.client_configuration.license_keys) else: YLogger.warning( self, "No client configuration setting for license_keys") else: YLogger.warning( self, "No configuration defined when loading license keys") def get_license_keys(self): return def initiate_logging(self, arguments): if arguments.logging is not None: with open(arguments.logging, 'r+', encoding="utf-8") as yml_data_file: logging_config = yaml.load(yml_data_file) logging.config.dictConfig(logging_config) YLogger.info(self, "Now logging under configuration") else: print( "Warning. No logging configuration file defined, using defaults..." ) def get_client_configuration(self): """ By overriding this class in you Configuration file, you can add new configurations and stil use the dynamic loader capabilities :return: Client configuration object """ raise NotImplementedError( "You must override this and return a subclassed client configuration" ) def load_configuration(self, arguments): if arguments.bot_root is None: if arguments.config_filename is not None: arguments.bot_root = os.path.dirname(arguments.config_filename) else: arguments.bot_root = "." print("No bot root argument set, defaulting to [%s]" % arguments.bot_root) if arguments.config_filename is not None: self._configuration = ConfigurationFactory.load_configuration_from_file( self.get_client_configuration(), arguments.config_filename, arguments.config_format, arguments.bot_root) else: print("No configuration file specified, using defaults only !") self._configuration = ProgramyConfiguration( self.get_client_configuration()) def load_scheduler(self): if self.configuration.client_configuration.scheduler is not None: self._scheduler = ProgramyScheduler( self, self.configuration.client_configuration.scheduler) self._scheduler.start() def create_client_context(self, userid): client_context = ClientContext(self, userid) client_context.bot = self._bot_factory.select_bot() client_context.brain = client_context.bot._brain_factory.select_brain() return client_context def load_renderer(self): try: if self.get_client_configuration().renderer is not None: clazz = ClassLoader.instantiate_class( self.get_client_configuration().renderer.renderer) return clazz(self) except Exception as e: YLogger.exception(None, "Failed to load config specified renderer", e) return self.get_default_renderer() def get_default_renderer(self): return TextRenderer(self) def process_question(self, client_context, question): raise NotImplementedError( "You must override this and implement the logic to create a response to the question" ) def render_response(self, client_context, response): raise NotImplementedError( "You must override this and implement the logic to process the response by rendering using a RCS renderer" ) def process_response(self, client_context, response): raise NotImplementedError( "You must override this and implement the logic to display the response to the user" ) def run(self): raise NotImplementedError( "You must override this and implement the logic to run the client")
def __init__(self, client, config): self._scheduled = False ProgramyScheduler.__init__(self, client, config)
def test_scheduled_unknown(self): client = MockClient() scheduler1 = ProgramyScheduler(client, SchedulerConfiguration()) scheduler1.scheduled("user1", "client1", "UNKNOWN", "Hello") self.assertIsNone(client._response)
def test_get_event_str_job_submission_event(self): event = JobSubmissionEvent ("code", "job_id", "jobstore", []) message = ProgramyScheduler.get_event_str(event) self.assertIsNotNone(message) self.assertEquals("JobSubmissionEvent [code] [job_id] [jobstore] [[]]", message)
def test_listener_event(self): event = JobEvent("code1", "id1", "mock") ProgramyScheduler.listener_event(event)
class BotClient(ResponseLogger): def __init__(self, id, argument_parser=None): self._id = id self._license_keys = LicenseKeys() self._storage = None self._scheduler = None self._email = None self._trigger_mgr = None self._configuration = None self._arguments = self.parse_arguments(argument_parser=argument_parser) self.initiate_logging(self.arguments) self._subsitutions = Substitutions() if self.arguments.substitutions is not None: self._subsitutions.load_substitutions(self.arguments.substitutions) self.load_configuration(self.arguments, subs=self._subsitutions) else: self.load_configuration(self.arguments) self.parse_configuration() self.load_storage() self._bot_factory = BotFactory(self, self.configuration.client_configuration) self.load_license_keys() self.get_license_keys() self._configuration.client_configuration.check_for_license_keys( self._license_keys) self.load_scheduler() self.load_renderer() self.load_email() self.load_trigger_manager() def ylogger_type(self): return "client" @property def configuration(self): return self._configuration @property def id(self): return self._id @property def arguments(self): return self._arguments @property def license_keys(self): return self._license_keys @property def scheduler(self): return self._scheduler @property def storage_factory(self): return self._storage @property def bot_factory(self): return self._bot_factory @property def renderer(self): return self._renderer @property def trigger_manager(self): return self._trigger_mgr def get_description(self): if self.configuration is not None: if self.configuration.client_configuration is not None: return self.configuration.client_configuration.description return "Bot Client" def add_client_arguments(self, parser=None): # Nothing to add return def parse_configuration(self): # Nothing to add return def parse_args(self, arguments, parsed_args): # Nothing to add return def parse_arguments(self, argument_parser): client_args = CommandLineClientArguments(self, parser=argument_parser) client_args.parse_args(self) return client_args def load_license_keys(self): if self.storage_factory.entity_storage_engine_available( StorageFactory.LICENSE_KEYS) is True: storage_engine = self.storage_factory.entity_storage_engine( StorageFactory.LICENSE_KEYS) keys_store = storage_engine.license_store() keys_store.load(self._license_keys) else: YLogger.warning(self, "No storage factory setting for license_keys") def get_license_keys(self): return def initiate_logging(self, arguments): if arguments.logging is not None: try: with open(arguments.logging, 'r+', encoding="utf-8") as yml_data_file: logging_config = yaml.load(yml_data_file) logging.config.dictConfig(logging_config) YLogger.debug(self, "Now logging under configuration") except Exception as excep: YLogger.exception(self, "Failed to open logging configuration [%s]", excep, arguments.logging) else: print( "Warning. No logging configuration file defined, using defaults..." ) def get_client_configuration(self): """ By overriding this class in you Configuration file, you can add new configurations and stil use the dynamic loader capabilities :return: Client configuration object """ raise NotImplementedError( "You must override this and return a subclassed client configuration" ) def load_configuration(self, arguments, subs: Substitutions = None): if arguments.bot_root is None: if arguments.config_filename is not None: arguments.bot_root = os.path.dirname(arguments.config_filename) else: arguments.bot_root = "." YLogger.debug( None, "No bot root argument set, defaulting to [%s]" % arguments.bot_root) if arguments.config_filename is not None: self._configuration = ConfigurationFactory.load_configuration_from_file( self.get_client_configuration(), arguments.config_filename, arguments.config_format, arguments.bot_root, subs) else: YLogger.debug( None, "No configuration file specified, using defaults only !") self._configuration = ProgramyConfiguration( self.get_client_configuration()) def load_scheduler(self): if self.configuration.client_configuration.scheduler is not None: YLogger.debug(None, "Loading Scheduler") self._scheduler = ProgramyScheduler( self, self.configuration.client_configuration.scheduler) self._scheduler.start() def load_email(self): if self._configuration.client_configuration.email is not None: YLogger.debug(None, "Loading Email Manager") self._email = EmailSender( self._configuration.client_configuration.email) def load_trigger_manager(self): if self._configuration.client_configuration.triggers is not None: YLogger.debug(None, "Loading Trigger Manager") self._trigger_mgr = TriggerManager.load_trigger_manager( self._configuration.client_configuration.triggers) def load_storage(self): self._storage = StorageFactory() if self.configuration.client_configuration.storage is not None: YLogger.debug(None, "Loading Storage Factory") self._storage.load_engines_from_config( self.configuration.client_configuration.storage) else: YLogger.debug(None, "No storage defined!") def load_renderer(self): try: if self.get_client_configuration().renderer is not None: YLogger.debug(None, "Loading Renderer") clazz = ClassLoader.instantiate_class( self.get_client_configuration().renderer.renderer) self._renderer = clazz(self) return except Exception as e: YLogger.exception(None, "Failed to load config specified renderer", e) self._renderer = self.get_default_renderer() def get_default_renderer(self): return TextRenderer(self) def create_client_context(self, userid): client_context = ClientContext(self, userid) client_context.bot = self._bot_factory.select_bot() client_context.brain = client_context.bot._brain_factory.select_brain() return client_context def startup(self): if self._trigger_mgr is not None: self._trigger_mgr.trigger(event=SystemTriggers.SYSTEM_STARTUP) def shutdown(self): if self._trigger_mgr is not None: self._trigger_mgr.trigger(event=SystemTriggers.SYSTEM_SHUTDOWN) def process_question(self, client_context, question): raise NotImplementedError( "You must override this and implement the logic to create a response to the question" ) def render_response(self, client_context, response): raise NotImplementedError( "You must override this and implement the logic to process the response by rendering" " using a RCS renderer") def process_response(self, client_context, response): raise NotImplementedError( "You must override this and implement the logic to display the response to the user" ) def run(self): raise NotImplementedError( "You must override this and implement the logic to run the client")
def test_get_event_str_scheduler_event(self): event = SchedulerEvent("code", "alias") message = ProgramyScheduler.get_event_str(event) self.assertIsNotNone(message) self.assertEqual("SchedulerEvent [code] [alias]", message)
def load_scheduler(self): if self.configuration.client_configuration.scheduler is not None: self._scheduler = ProgramyScheduler(self, self.configuration.client_configuration.scheduler) self._scheduler.start()
def test_get_event_str_job_submission_event(self): event = JobSubmissionEvent("code", "job_id", "jobstore", []) message = ProgramyScheduler.get_event_str(event) self.assertIsNotNone(message) self.assertEqual("JobSubmissionEvent [code] [job_id] [jobstore] [[]]", message)
def test_get_event_str_job_event(self): event = JobEvent ("code", "id", "jobstore") message = ProgramyScheduler.get_event_str(event) self.assertIsNotNone(message) self.assertEquals("JobEvent [code] [id] [jobstore] [None]", message)
def test_get_event_str_job_execution_event_with_exception(self): scheduled_run_time = datetime.strptime("10/04/18 19:02", "%d/%m/%y %H:%M") event = JobExecutionEvent ("code", "job_id", "jobstore", scheduled_run_time, retval=1, exception=Exception("Test Error")) message = ProgramyScheduler.get_event_str(event) self.assertIsNotNone(message) self.assertEquals("JobExecutionEvent [code] [job_id] [jobstore] [2018-04-10 19:02:00] [1] [Test Error]", message)
def load_scheduler(self): if self.configuration.client_configuration.scheduler is not None: YLogger.debug(None, "Loading Scheduler") self._scheduler = ProgramyScheduler( self, self.configuration.client_configuration.scheduler) self._scheduler.start()
class BotClient(ResponseLogger): def __init__(self, id, argument_parser=None): self._id = id self._arguments = self.parse_arguments(argument_parser=argument_parser) self.initiate_logging(self.arguments) self._configuration = None self.load_configuration(self.arguments) self.parse_configuration() self._bot_factory = BotFactory(self, self.configuration.client_configuration) self._license_keys = LicenseKeys() self.load_license_keys() self.get_license_keys() self._scheduler = None self.load_scheduler() self._renderer = self.load_renderer() def ylogger_type(self): return "client" @property def configuration(self): return self._configuration @property def id(self): return self._id @property def arguments(self): return self._arguments @property def license_keys(self): return self._license_keys @property def scheduler(self): return self._scheduler @property def bot_factory(self): return self._bot_factory @property def renderer(self): return self._renderer def get_description(self): raise NotImplementedError("You must override this and return a client description") def add_client_arguments(self, parser=None): # Nothing to add return def parse_configuration(self): # Nothing to add return def parse_args(self, arguments, parsed_args): # Nothing to add return def parse_arguments(self, argument_parser): client_args = CommandLineClientArguments(self, parser=argument_parser) client_args.parse_args(self) return client_args def load_license_keys(self): if self.configuration is not None: if self.configuration.client_configuration.license_keys is not None: self._license_keys.load_license_key_file(self.configuration.client_configuration.license_keys) else: YLogger.warning(self, "No client configuration setting for license_keys") else: YLogger.warning(self, "No configuration defined when loading license keys") def get_license_keys(self): return def initiate_logging(self, arguments): if arguments.logging is not None: with open(arguments.logging, 'r+', encoding="utf-8") as yml_data_file: logging_config = yaml.load(yml_data_file) logging.config.dictConfig(logging_config) YLogger.info(self, "Now logging under configuration") else: print("Warning. No logging configuration file defined, using defaults...") def get_client_configuration(self): """ By overriding this class in you Configuration file, you can add new configurations and stil use the dynamic loader capabilities :return: Client configuration object """ raise NotImplementedError("You must override this and return a subclassed client configuration") def load_configuration(self, arguments): if arguments.bot_root is None: if arguments.config_filename is not None: arguments.bot_root = os.path.dirname(arguments.config_filename) else: arguments.bot_root = "." print("No bot root argument set, defaulting to [%s]" % arguments.bot_root) if arguments.config_filename is not None: self._configuration = ConfigurationFactory.load_configuration_from_file(self.get_client_configuration(), arguments.config_filename, arguments.config_format, arguments.bot_root) else: print("No configuration file specified, using defaults only !") self._configuration = ProgramyConfiguration(self.get_client_configuration()) def load_scheduler(self): if self.configuration.client_configuration.scheduler is not None: self._scheduler = ProgramyScheduler(self, self.configuration.client_configuration.scheduler) self._scheduler.start() def create_client_context(self, userid): client_context = ClientContext(self, userid) client_context.bot = self._bot_factory.select_bot() client_context.brain = client_context.bot._brain_factory.select_brain() return client_context def load_renderer(self): try: if self.get_client_configuration().renderer is not None: clazz = ClassLoader.instantiate_class(self.get_client_configuration().renderer.renderer) return clazz(self) except Exception as e: YLogger.exception(None, "Failed to load config specified renderer", e) return self.get_default_renderer() def get_default_renderer(self): return TextRenderer(self) def process_question(self, client_context, question): raise NotImplementedError("You must override this and implement the logic to create a response to the question") def render_response(self, client_context, response): raise NotImplementedError("You must override this and implement the logic to process the response by rendering using a RCS renderer") def process_response(self, client_context, response): raise NotImplementedError("You must override this and implement the logic to display the response to the user") def run(self): raise NotImplementedError("You must override this and implement the logic to run the client")