def test_load_with_subs(self): subs = Substitutions() subs.add_substitute("$ALLOW_SYSTEM", True) config_data = XMLConfigurationFile() self.assertIsNotNone(config_data) configuration = config_data.load_from_text("""<?xml version="1.0" encoding="UTF-8" ?> <root> <brain> <overrides> <allow_system_aiml>true</allow_system_aiml> <allow_learn_aiml>true</allow_learn_aiml> <allow_learnf_aiml>true</allow_learnf_aiml> </overrides> </brain> </root>""", ConsoleConfiguration(), ".") self.assertIsNotNone(configuration) section = config_data.get_section("brainx") self.assertIsNone(section) section = config_data.get_section("brain") self.assertIsNotNone(section) child_section = config_data.get_section("overrides", section) self.assertIsNotNone(child_section) self.assertEqual(True, config_data.get_option(child_section, "allow_system_aiml")) self.assertEqual(True, config_data.get_bool_option(child_section, "allow_system_aiml")) self.assertEqual(False, config_data.get_bool_option(child_section, "other_value"))
def test_load_with_subs(self): subs = Substitutions() subs.add_substitute("$ALLOW_SYSTEM", True) config_data = YamlConfigurationFile() self.assertIsNotNone(config_data) configuration = config_data.load_from_text(""" brain: overrides: allow_system_aiml: true allow_learn_aiml: true allow_learnf_aiml: true """, ConsoleConfiguration(), ".") self.assertIsNotNone(configuration) section = config_data.get_section("brainx") self.assertIsNone(section) section = config_data.get_section("brain") self.assertIsNotNone(section) child_section = config_data.get_section("overrides", section) self.assertIsNotNone(child_section) self.assertEqual(True, config_data.get_option(child_section, "allow_system_aiml")) self.assertEqual(True, config_data.get_bool_option(child_section, "allow_system_aiml")) self.assertEqual(False, config_data.get_bool_option(child_section, "other_value"))
def test_add_duplicate(self): sub = Substitutions() sub.add_substitute("$FIRSTNAME", "Fred") sub.add_substitute("$FIRSTNAME", "Fred") self.assertTrue(sub.has_substitute("$FIRSTNAME"))
def test_load_bad_subs(self): sub = Substitutions() sub.load_substitutions( os.path.dirname(__file__) + os.sep + "bad_subs.txt") with self.assertRaises(ValueError): _ = sub.get_substitute("$FIRSTNAME")
def test_load(self): sub = Substitutions() sub.load_substitutions(os.path.dirname(__file__) + os.sep + "subs.txt") self.assertEquals("Fred", sub.get_substitute("$FIRSTNAME")) self.assertEquals("West", sub.get_substitute("$SURNAME")) self.assertEquals("Mary", sub.get_substitute("$WIFE")) with self.assertRaises(ValueError): sub.get_substitute("$NUMBER")
def __init__(self, botid, argument_parser=None): self._id = botid self._license_keys = LicenseKeys() self._storage = None self._scheduler = None self._email = None self._trigger_mgr = None self._configuration = None self._ping_responder = None self._questions = 0 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) self.parse_configuration() self.load_storage() self.load_license_keys() self.get_license_keys() self._configuration.client_configuration.check_for_license_keys( self._license_keys) self._bot_factory = BotFactory(self, self.configuration.client_configuration) self.load_scheduler() self._renderer = None self.load_renderer() self.load_email() self.load_trigger_manager() self.load_ping_responder() self.post_initialise()
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._bot_root = '.' self._engine_version = None self._arguments = self.parse_arguments(argument_parser=argument_parser) self._engine_version = self._arguments.version 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 test_substitutions(self): sub = Substitutions() sub.load_substitutions(os.path.dirname(__file__) + os.sep + "subs.txt") self.assertEquals("My name is Fred West", sub.replace("My name is $FIRSTNAME $SURNAME")) self.assertEquals("My name is FredWest", sub.replace("My name is $FIRSTNAME$SURNAME"))
def test_basics(self): sub = Substitutions() sub.add_substitute("$FIRSTNAME", "Fred") sub.add_substitute("$SURNAME", "West") sub.add_substitute("$WIFE", "Mary") self.assertTrue(sub.has_substitute("$FIRSTNAME")) self.assertFalse(sub.has_substitute("$FRED")) self.assertEquals("Fred", sub.get_substitute("$FIRSTNAME")) self.assertEquals("West", sub.get_substitute("$SURNAME")) self.assertEquals("Mary", sub.get_substitute("$WIFE")) with self.assertRaises(ValueError): sub.get_substitute("$NUMBER") sub.empty() self.assertFalse(sub.has_substitute("$FIRSTNAME")) self.assertFalse(sub.has_substitute("$SURNAME")) self.assertFalse(sub.has_substitute("$WIFE"))
def test_replace_subs(self): config = MockBaseConfigurationFile() subs = Substitutions() subs.add_substitute("TEST", "VALUE") self.assertEquals("VALUE", config._replace_subs(subs, "TEST"))
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 __init__(self, id, config_file_path, src_root_path=None): """ BotClient that can be initilized in runtime from YAML config WARNING this module changes CWD (Current Working Directory)! ProgramY has assumptions about current directories and uses environmental variables to specify search paths when launched from bash scripts. First, ProgramY uses file paths relative to config file. Second, ProgramY allows to specify paths to modules which are in dot notation relative to project root, which is different from config dir and usually placed 2 directories higher In this module we gather all this configurations via parameters. :param id: str, unique identifier of the bot :param config_file_path: path to the YAML config file :param src_root_path: sometimes YAML config path asserts that we reference to modules which are part of another project, and src_modules_root_path - is a path from which we look for specified modules. For example YAML config joiner: classname: templatey.processors.sentence_joiner_deduplicator.SentenceJoinerDeDuplicator means that a class SentenceJoinerDeDuplicator will be searched from src_modules_root_path by appending dot prefixes. """ self._id = id self._license_keys = LicenseKeys() self._storage = None self._scheduler = None self._email = None self._trigger_mgr = None self._configuration = None self._ping_responder = None self._questions = 0 self._arguments = self.parse_arguments(argument_parser=None) # hack: if self._arguments._logging == 10: self._arguments._logging = None self.initiate_logging(self.arguments) self._subsitutions = Substitutions() if self.arguments.substitutions is not None: self._subsitutions.load_substitutions(self.arguments.substitutions) # specify configuration file self._config_filename = config_file_path self.load_configuration(self.arguments) # self.parse_configuration() self.load_storage() ############################################################################## # set path because config uses relative paths # this required so the files specified as relative paths in YAML will be interpreted # correctly like in the example: # categories_storage: # dirs: ../../storage/categories # subdirs: true # extension: .aiml current_dir_path = os.path.dirname(self._config_filename) os.chdir(current_dir_path) ############################################################################## ############################################################################## # to be able to find modules of dream aiml such as SentenceDeduplicator if not src_root_path: src_root_path = os.path.dirname(os.path.dirname(current_dir_path)) src_root_path += "/src" sys.path.append(src_root_path) ############################################################################## 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() self.load_ping_responder()
def _replace_subs(self, subs: Substitutions, value): if subs is not None: return subs.replace(value) return value
def test_substitutions_no_file(self): sub = Substitutions() sub.load_substitutions(None)