示例#1
0
class TemplateGraphListProcessingTests(unittest.TestCase):
    def setUp(self):
        self.parser = TemplateGraph()
        self.assertIsNotNone(self.parser)

        self.test_brain = None
        test_config = ClientConfiguration()
        self.test_bot = Bot(Brain(BrainConfiguration()),
                            config=test_config.bot_configuration)
        self.test_clientid = "testid"

    def test_first(self):
        template = ET.fromstring("""
            <template>
                <first>one two three four</first>
            </template>
            """)
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertEqual(ast.resolve(None, None), "one")

    def test_rest(self):
        template = ET.fromstring("""
            <template>
                <rest>one two three four</rest>
            </template>
            """)
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertEqual(ast.resolve(None, None), "two three four")
示例#2
0
class TemplateGraphThinkTests(unittest.TestCase):

    def setUp(self):
        self.parser = TemplateGraph()
        self.assertIsNotNone(self.parser)

        self.test_brain = None
        self.test_sentence = Sentence("test sentence")
        self.test_sentence._stars = ['one', 'two', 'three', 'four', 'five', 'six']
        self.test_sentence._thatstars = ["*"]
        self.test_sentence._topicstars = ["*"]

        test_config = ClientConfiguration()

        self.test_bot = Bot(Brain(BrainConfiguration()), config=test_config.bot_configuration)
        self.test_clientid = "testid"

        conversation = self.test_bot.get_conversation(self.test_clientid)
        question = Question.create_from_sentence(self.test_sentence)
        conversation._questions.append(question)

    def test_think(self):
        template = ET.fromstring("""
			<template>
				<think>XYZ</think>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertEqual(ast.resolve(None, None), "")
示例#3
0
class TemplateGraphTopicTests(unittest.TestCase):
    def setUp(self):
        self.parser = TemplateGraph()
        self.assertIsNotNone(self.parser)

        self.test_brain = None
        self.test_sentence = Sentence("test sentence")
        self.test_sentence._stars = [
            'one', 'two', 'three', 'four', 'five', 'six'
        ]
        self.test_sentence._thatstars = ["*"]
        self.test_sentence._topicstars = ["*"]

        test_config = ClientConfiguration()

        self.test_bot = Bot(Brain(BrainConfiguration()),
                            config=test_config.bot_configuration)
        self.test_clientid = "testid"

        conversation = self.test_bot.get_conversation(self.test_clientid)
        question = Question.create_from_sentence(self.test_sentence)
        conversation._questions.append(question)

    def test_topicstar_index_as_attrib_full(self):
        template = ET.fromstring("""
			<template>
				<topicstar index="1"></topicstar>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertEqual(ast.children[0].to_string(), "TOPICSTAR Index=1")
        self.assertEqual(ast.resolve(self.test_bot, self.test_clientid), "*")
示例#4
0
class TemplateGraphSraixTests(unittest.TestCase):
    def setUp(self):
        self.parser = TemplateGraph()
        self.assertIsNotNone(self.parser)

        self.test_brain = None
        self.test_sentence = Sentence("test sentence")
        self.test_sentence._stars = [
            'one', 'two', 'three', 'four', 'five', 'six'
        ]
        self.test_sentence._thatstars = ["*"]
        self.test_sentence._topicstars = ["*"]

        test_config = ClientConfiguration()

        self.test_bot = Bot(Brain(BrainConfiguration()),
                            config=test_config.bot_configuration)
        self.test_clientid = "testid"

        conversation = self.test_bot.get_conversation(self.test_clientid)
        question = Question.create_from_sentence(self.test_sentence)
        conversation._questions.append(question)

    def test_sraix_template_params_as_attribs(self):
        template = ET.fromstring("""
            <template>
                <sraix host="hostname" botid="testbot" hint="test query" apikey="1234567890" service="/ask">
                    Ask this question
                </sraix>
            </template>
            """)
        ast = self.parser.parse_template_expression(template)

    def test_sraix_template_params_as_children(self):
        template = ET.fromstring("""
            <template>
                <sraix>
                    <host>hostname</host>
                    <botid>testbot</botid>
                    <hint>test query</hint>
                    <apikey>1234567890</apikey>
                    <service>/ask</service>
                    Ask this question
                </sraix>
            </template>
            """)
        ast = self.parser.parse_template_expression(template)
示例#5
0
class TemplateGraphBasicTests(unittest.TestCase):
    def setUp(self):
        self.parser = TemplateGraph()
        self.assertIsNotNone(self.parser)

        self.test_brain = None
        self.test_sentence = Sentence("test sentence")
        self.test_sentence._stars = [
            'one', 'two', 'three', 'four', 'five', 'six'
        ]
        self.test_sentence._thatstars = ["*"]
        self.test_sentence._topicstars = ["*"]

        test_config = ClientConfiguration()

        self.test_bot = Bot(Brain(BrainConfiguration()),
                            config=test_config.bot_configuration)
        self.test_clientid = "testid"

        conversation = self.test_bot.get_conversation(self.test_clientid)
        question = Question.create_from_sentence(self.test_sentence)
        conversation._questions.append(question)

    def test_template_no_content(self):
        template = ET.fromstring("""
			<template>
			</template>
			""")
        with self.assertRaises(ParserException):
            ast = self.parser.parse_template_expression(template)

    def test_base_template(self):
        template = ET.fromstring("""
			<template>HELLO WORLD</template>
			""")
        ast = self.parser.parse_template_expression(template)

        self.assertIsNotNone(ast)
        self.assertEqual(2, len(ast.children))
        self.assertIsInstance(ast.children[0], TemplateWordNode)
        self.assertIsInstance(ast.children[1], TemplateWordNode)
示例#6
0
class TemplateGraphBasicRequestResponseTests(unittest.TestCase):
    def setUp(self):
        self.parser = TemplateGraph()
        self.assertIsNotNone(self.parser)

        self.test_brain = None
        self.test_sentence = Sentence("test sentence")
        self.test_sentence._stars = [
            'one', 'two', 'three', 'four', 'five', 'six'
        ]
        self.test_sentence._thatstars = ["*"]
        self.test_sentence._topicstars = ["*"]

        test_config = ClientConfiguration()

        self.test_bot = Bot(Brain(BrainConfiguration()),
                            config=test_config.bot_configuration)
        self.test_clientid = "testid"

        conversation = self.test_bot.get_conversation(self.test_clientid)
        question = Question.create_from_sentence(self.test_sentence)
        conversation._questions.append(question)

    def test_response_index_as_attrib_full(self):
        template = ET.fromstring("""
            <template>
                <response index="9"></response>
            </template>
            """)
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)

    def test_request_index_as_attrib_full(self):
        template = ET.fromstring("""
			<template>
				<request index="8"></request>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
示例#7
0
class TemplateGraphSystemTests(unittest.TestCase):

    def setUp(self):
        self.parser = TemplateGraph()
        self.assertIsNotNone(self.parser)

        self.test_brain = None
        self.test_sentence = Sentence("test sentence")
        self.test_sentence._stars = ['one', 'two', 'three', 'four', 'five', 'six']
        self.test_sentence._thatstars = ["*"]
        self.test_sentence._topicstars = ["*"]

        test_config = ClientConfiguration()

        self.test_bot = Bot(Brain(BrainConfiguration()), config=test_config.bot_configuration)
        self.test_clientid = "testid"

        conversation = self.test_bot.get_conversation(self.test_clientid)
        question = Question.create_from_sentence(self.test_sentence)
        conversation._questions.append(question)

    def test_system_timeout_as_attrib_full(self):
        template = ET.fromstring("""
			<template>
				<system timeout="1000">echo "Hello World"</system>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertEqual(ast.resolve(self.test_bot, self.test_clientid), "Hello World")

    def test_size(self):
        template = ET.fromstring("""
			<template>
				<size />
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertEqual(ast.resolve(self.test_bot, self.test_clientid), "0")
示例#8
0
class TemplateGraphLearnTests(unittest.TestCase):
    def setUp(self):
        self.parser = TemplateGraph(AIMLParser())
        self.assertIsNotNone(self.parser)

        self.test_brain = None
        self.test_sentence = Sentence("test sentence")
        self.test_sentence._stars = [
            'one', 'two', 'three', 'four', 'five', 'six'
        ]
        self.test_sentence._thatstars = ["*"]
        self.test_sentence._topicstars = ["*"]

        test_config = ClientConfiguration()

        self.test_bot = Bot(Brain(BrainConfiguration()),
                            config=test_config.bot_configuration)
        self.test_clientid = "testid"

        conversation = self.test_bot.get_conversation(self.test_clientid)
        question = Question.create_from_sentence(self.test_sentence)
        conversation._questions.append(question)

    def test_eval_simple(self):
        template = ET.fromstring("""
			<template>
				<eval>sometext</eval>
			</template>
			""")

        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)
        self.assertEqual(len(ast.children), 1)

        eval_node = ast.children[0]
        self.assertIsNotNone(eval_node)
        self.assertIsInstance(eval_node, TemplateEvalNode)

        self.assertIsNotNone(eval_node.children)
        self.assertEqual(len(eval_node.children), 1)
        self.assertIsInstance(eval_node.children[0], TemplateWordNode)

        self.assertEqual(eval_node.resolve(self.test_bot, self.test_clientid),
                         "sometext")

    def test_learn_simple(self):
        template = ET.fromstring("""
			<template>
				<learn>
				    <category>
				        <pattern>HELLO <eval>WORLD</eval> THERE</pattern>
				        <template>HIYA</template>
				    </category>
				</learn>
			</template>
			""")

        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)
        self.assertEqual(len(ast.children), 1)

        learn_node = ast.children[0]
        self.assertIsNotNone(learn_node)
        self.assertIsInstance(learn_node, TemplateLearnNode)
        self.assertIsNotNone(learn_node._pattern)
        self.assertIsInstance(learn_node._pattern, ET.Element)
        self.assertIsNotNone(learn_node._topic)
        self.assertIsInstance(learn_node._topic, ET.Element)
        self.assertIsNotNone(learn_node._that)
        self.assertIsInstance(learn_node._that, ET.Element)
        self.assertIsNotNone(learn_node._template)
        self.assertIsInstance(learn_node._template, TemplateNode)

        resolved = learn_node.resolve(self.test_bot, self.test_clientid)
        self.assertEqual(resolved, "")

        response = self.test_bot.ask_question(self.test_clientid,
                                              "HELLO WORLD THERE")
        self.assertEqual("HIYA", response)

    def test_learnf_simple(self):
        template = ET.fromstring("""
			<template>
				<learnf>
				    <category>
				        <pattern>HELLO <eval>WORLD</eval> THERE</pattern>
				        <template>HIYA</template>
				    </category>
				</learnf>
			</template>
			""")

        self.test_bot.brain._configuration._aiml_files = BrainFileConfiguration(
            "/tmp", ".aiml", False)

        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)
        self.assertEqual(len(ast.children), 1)

        learn_node = ast.children[0]
        self.assertIsNotNone(learn_node)
        self.assertIsInstance(learn_node, TemplateLearnNode)
        self.assertIsNotNone(learn_node._pattern)
        self.assertIsInstance(learn_node._pattern, ET.Element)
        self.assertIsNotNone(learn_node._topic)
        self.assertIsInstance(learn_node._topic, ET.Element)
        self.assertIsNotNone(learn_node._that)
        self.assertIsInstance(learn_node._that, ET.Element)
        self.assertIsNotNone(learn_node._template)
        self.assertIsInstance(learn_node._template, TemplateNode)

        resolved = learn_node.resolve(self.test_bot, self.test_clientid)
        self.assertEqual(resolved, "")

        response = self.test_bot.ask_question(self.test_clientid,
                                              "HELLO WORLD THERE")
        self.assertEqual("HIYA", response)
示例#9
0
class AIMLParser(object):
    def __init__(self, supress_warnings=False, stop_on_invalid=False):
        self._supress_warnings = supress_warnings
        self.stop_on_invalid = stop_on_invalid
        self.pattern_parser = PatternGraph()
        self.template_parser = TemplateGraph(self)
        self._aiml_loader = AIMLLoader(self)
        self._num_categories = 0
        self._duplicates = None
        self._errors = None

    @property
    def supress_warnings(self):
        return self._supress_warnings

    @property
    def num_categories(self):
        return self._num_categories

    def create_debug_storage(self, brain_configuration):
        if brain_configuration.aiml_files.errors is not None:
            self._errors = []
        if brain_configuration.aiml_files.duplicates is not None:
            self._duplicates = []

    def save_debug_files(self, brain_configuration):

        if brain_configuration.aiml_files.errors is not None:
            logging.info("Saving aiml errors to file [%s]" %
                         brain_configuration.aiml_files.errors)
            try:
                with open(brain_configuration.aiml_files.errors,
                          "w+") as errors_file:
                    for error in self._errors:
                        errors_file.write(error)
            except Exception as e:
                logging.exception(e)

        if brain_configuration.aiml_files.duplicates is not None:
            logging.info("Saving aiml duplicates to file [%s]" %
                         brain_configuration.aiml_files.duplicates)
            try:
                with open(brain_configuration.aiml_files.duplicates,
                          "w+") as duplicates_file:
                    for duplicate in self._duplicates:
                        duplicates_file.write(duplicate)
            except Exception as e:
                logging.exception(e)

    def display_debug_info(self, brain_configuration):
        if self._errors is not None:
            logging.info(
                "Found a total of %d errors in your grammrs, check out [%s] for details"
                % (len(self._errors), brain_configuration.aiml_files.errors))
        if self._duplicates is not None:
            logging.info(
                "Found a total of %d duplicate patterns in your grammrs, check out [%s] for details"
                % (len(self._duplicates),
                   brain_configuration.aiml_files.duplicates))

    def load_files_from_directory(self, brain_configuration):
        start = datetime.datetime.now()
        aimls_loaded = self._aiml_loader.load_dir_contents(
            brain_configuration.aiml_files.files,
            brain_configuration.aiml_files.directories,
            brain_configuration.aiml_files.extension)
        stop = datetime.datetime.now()
        diff = stop - start
        logging.info("Total processing time %f.2 secs" % diff.total_seconds())
        logging.info("Loaded a total of %d aiml files with %d categories" %
                     (len(aimls_loaded), self.num_categories))
        if diff.total_seconds() > 0:
            logging.info("Thats approx %f aiml files per sec" %
                         (len(aimls_loaded) / diff.total_seconds()))

    def load_single_file(self, brain_configuration):
        start = datetime.datetime.now()
        self._aiml_loader.load_single_file_contents(
            brain_configuration.aiml_files.file)
        stop = datetime.datetime.now()
        diff = stop - start
        logging.info("Total processing time %f.2 secs" % diff.total_seconds())
        logging.info("Loaded a single aiml file with %d categories" %
                     (self.num_categories))

    def load_aiml(self, brain_configuration: BrainConfiguration):

        self._supress_warnings = brain_configuration.supress_warnings

        if brain_configuration.aiml_files is not None:

            self.create_debug_storage(brain_configuration)

            if brain_configuration.aiml_files.files is not None:
                self.load_files_from_directory(brain_configuration)

            elif brain_configuration.aiml_files.file is not None:
                self.load_single_file(brain_configuration)

            else:
                logging.info(
                    "No AIML files or file defined in configuration to load")

            self.save_debug_files(brain_configuration)

            self.display_debug_info(brain_configuration)

        else:
            logging.info(
                "No AIML files or file defined in configuration to load")

        if brain_configuration.dump_to_file is not None:
            logging.debug("Dumping AIML Graph as tree to [%s]" %
                          brain_configuration.dump_to_file)
            self.pattern_parser.dump_to_file(brain_configuration.dump_to_file)

    def parse_from_file(self, filename):
        """
        Parse an AIML file and return all the cateogeries found in the file
        :param filename: Name of file to parse
        :return list of categories parsed from file:
        """
        logging.info("Loading aiml file: " + filename)

        try:
            #print("Parsing raw XML Tree")
            tree = ET.parse(filename, parser=LineNumberingParser())
            #print("Parsed...")
            aiml = tree.getroot()
            if aiml is None or aiml.tag != 'aiml':
                raise ParserException("Error, root tag is not <aiml>",
                                      filename=filename)
            else:
                #print("Parsing loaded AIML tree")
                #start = datetime.datetime.now()
                self.parse_aiml(aiml, filename)
                #stop = datetime.datetime.now()
                #diff = stop - start
                #print("Parsed in %f sec"%(diff.total_seconds()))
        except Exception as e:
            logging.exception(e)
            logging.error(
                "Failed to load contents of AIML file from [%s] - [%s]" %
                (filename, e))

    def parse_from_text(self, text):
        """
         Parse an AIML text version of an aiml file and return all the cateogeries found in the file
         :param text: Fully validated AIML snippet
         :return list of categories parsed from file:
         """

        aiml = ET.fromstring(text)

        if aiml is None or aiml.tag != 'aiml':
            raise ParserException("Error, root tag is not <aiml>",
                                  filename="text")
        else:
            self.parse_aiml(aiml, "text")

    #########################################################################################
    #
    #   <?xml version = "1.0" encoding = "UTF-8"?>
    #   <aiml>
    #       <category>
    #           :
    #       </category>
    #       <topic>
    #           <category>
    #           :
    #           </category>
    #       </topic>
    #   </aiml>
    #

    def handle_aiml_duplicate(self, dupe_excep, filename):
        if self._duplicates is not None:
            dupe_excep.filename = filename
            msg = dupe_excep.format_message()
            self._duplicates.append(msg + "\n")
            logging.error(msg)

    def handle_aiml_error(self, parser_excep, filename):
        parser_excep.filename = filename
        msg = parser_excep.format_message()
        logging.error(msg)

        if self._errors is not None:
            self._errors.append(msg + "\n")

        if self.stop_on_invalid is True:
            raise parser_excep

    def parse_aiml(self, aiml_xml, filename):
        self.parse_version(aiml_xml)

        categories_found = False
        for expression in aiml_xml:
            if expression.tag == 'topic':
                try:
                    self.parse_topic(expression)
                    categories_found = True

                except DuplicateGrammarException as dupe_excep:
                    self.handle_aiml_duplicate(dupe_excep, filename)

                except ParserException as parser_excep:
                    self.handle_aiml_error(parser_excep, filename)

            elif expression.tag == 'category':
                try:
                    self.parse_category(expression)
                    categories_found = True

                except DuplicateGrammarException as dupe_excep:
                    self.handle_aiml_duplicate(dupe_excep, filename)

                except ParserException as parser_excep:
                    self.handle_aiml_error(parser_excep, filename)

            else:
                raise ParserException("Error, unknown top level tag, %s" %
                                      expression.tag,
                                      xml_element=expression)

        if categories_found is False:
            logging.warning("no categories in aiml file")
            if self.stop_on_invalid is True:
                raise ParserException("Error, no categories in aiml file",
                                      filename=filename)

    #########################################################################################
    #
    # AIML_VERSION ::== 0.9 | 1.0 | 1.1 | 2.0
    #

    def parse_version(self, aiml):
        if 'version' in aiml.attrib:
            version = aiml.attrib['version']
            if version not in ['0.9', '1.0', '1.1', '2.0']:
                if self._supress_warnings is False:
                    logging.warning(
                        "Version number not a supported version: %s", version)
        else:
            if self._supress_warnings is False:
                logging.warning("No version info, defaulting to 2.0")
            version = "2.0"
        return version

    #########################################################################################
    #
    # TOPIC_EXPRESSION:: == <topic name = "PATTERN_EXPRESSION" > (CATEGORY_EXPRESSION) + < / topic >
    #
    # PATTERN_EXPRESSION:: == WORD | PRIORITY_WORD | WILDCARD | SET_STATEMENT | PATTERN_SIDE_BOT_PROPERTY_EXPRESSION
    # PATTERN_EXPRESSION:: == PATTERN_EXPRESSION PATTERN_EXPRESSION
    #
    # This means both topic and that can also be a set of words, stars, hash, sets and bots
    #
    # CATEGORY_EXPRESSION:: == <category>
    #                               <pattern> PATTERN_EXPRESSION </pattern>
    #                              (<that> PATTERN_EXPRESSION </that>)
    #                              (<topic> PATTERN_EXPRESSION </topic>)
    #                              < template > TEMPLATE_EXPRESSION < / template >
    #                          </category>

    def parse_topic(self, topic_element):

        if 'name' in topic_element.attrib:
            name = topic_element.attrib['name']
            if name is None or len(name) == 0:
                raise ParserException("Topic name empty or null",
                                      xml_element=topic_element)
            xml = "<topic>%s</topic>" % name
            logging.info("Topic attrib converted to %s", xml)
            topic_pattern = ET.fromstring(xml)
        else:
            raise ParserException("Error, missing name attribute for topic",
                                  xml_element=topic_element)

        category_found = False
        for child in topic_element:
            if child.tag == 'category':
                self.parse_category(child, topic_pattern)
                category_found = True
            else:
                raise ParserException("Error unknown child node of topic, %s" %
                                      child.tag,
                                      xml_element=topic_element)

        if category_found is False:
            raise ParserException("Error, no categories in topic",
                                  xml_element=topic_element)

    def find_topic(self, category_xml, topic_element=None):
        topics = category_xml.findall('topic')
        if topic_element is not None:
            if len(topics) > 0:
                raise ParserException(
                    "Error, topic exists in category AND as parent node",
                    xml_element=category_xml)

        else:
            if len(topics) > 1:
                raise ParserException(
                    "Error, multiple <topic> nodes found in category",
                    xml_element=category_xml)
            elif len(topics) == 1:
                topic_element = topics[0]
            else:
                topic_element = ET.fromstring("<topic>*</topic>")

        return topic_element

    def find_that(self, category_xml):
        thats = category_xml.findall('that')
        if len(thats) > 1:
            raise ParserException(
                "Error, multiple <that> nodes found in category",
                xml_element=category_xml)
        elif len(thats) == 1:
            that_element = thats[0]
        else:
            that_element = ET.fromstring("<that>*</that>")
        return that_element

    def get_template(self, category_xml):
        templates = category_xml.findall('template')
        if len(templates) == 0:
            raise ParserException("Error, no template node found in category",
                                  xml_element=category_xml)
        elif len(templates) > 1:
            raise ParserException(
                "Error, multiple <template> nodes found in category",
                xml_element=category_xml)
        else:
            return self.template_parser.parse_template_expression(templates[0])

    def get_pattern(self, category_xml):
        patterns = category_xml.findall('pattern')
        if len(patterns) == 0:
            raise ParserException("Error, no pattern node found in category",
                                  xml_element=category_xml)
        elif len(patterns) > 1:
            raise ParserException(
                "Error, multiple <pattern> nodes found in category",
                xml_element=category_xml)
        else:
            return patterns[0]

    def parse_category(self,
                       category_xml,
                       topic_element=None,
                       add_to_graph=True):

        topic_element = self.find_topic(category_xml, topic_element)

        that_element = self.find_that(category_xml)

        template_graph_root = self.get_template(category_xml)

        pattern = self.get_pattern(category_xml)

        if add_to_graph is True:
            self.pattern_parser.add_pattern_to_graph(pattern, topic_element,
                                                     that_element,
                                                     template_graph_root)
            self._num_categories += 1

        return (pattern, topic_element, that_element, template_graph_root)

    def match_sentence(self, bot, clientid, pattern_sentence, topic_pattern,
                       that_pattern):

        topic_sentence = Sentence(topic_pattern)
        that_sentence = Sentence(that_pattern)

        logging.debug(
            "AIML Parser matching sentence [%s], topic=[%s], that=[%s] ",
            pattern_sentence.text(), topic_pattern, that_pattern)

        sentence = Sentence()
        sentence.append_sentence(pattern_sentence)
        sentence.append_word('__TOPIC__')
        sentence.append_sentence(topic_sentence)
        sentence.append_word('__THAT__')
        sentence.append_sentence(that_sentence)
        logging.debug("Matching [%s]" % sentence.words_from_current_pos(0))

        context = MatchContext()

        template = self.pattern_parser._root_node.match(
            bot, clientid, context, sentence)

        if template is not None:
            context._template_node = template

            context.list_matches()

            # Save the matched context for the associated sentence
            pattern_sentence.matched_context = context

            return context

        return None
示例#10
0
class TemplateGraphRandomTests(unittest.TestCase):

    def setUp(self):
        self.parser = TemplateGraph()
        self.assertIsNotNone(self.parser)

        self.test_brain = None
        self.test_sentence = Sentence("test sentence")
        self.test_sentence._stars = ['one', 'two', 'three', 'four', 'five', 'six']
        self.test_sentence._thatstars = ["*"]
        self.test_sentence._topicstars = ["*"]

        test_config = ClientConfiguration()

        self.test_bot = Bot(Brain(BrainConfiguration()), config=test_config.bot_configuration)
        self.test_clientid = "testid"

        conversation = self.test_bot.get_conversation(self.test_clientid)
        question = Question.create_from_sentence(self.test_sentence)
        conversation._questions.append(question)

    def test_random_template_no_li(self):
        template = ET.fromstring("""
			<template>
				<random>
				</random>
			</template>
			""")
        with self.assertRaises(ParserException):
            ast = self.parser.parse_template_expression(template)

    def test_random_template(self):
        template = ET.fromstring("""
			<template>
				<random>
					<li>1</li>
					<li>2</li>
					<li>3</li>
				</random>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)

        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)
        self.assertIsNotNone(ast.children[0])
        self.assertIsInstance(ast.children[0], TemplateRandomNode)
        self.assertEqual(3, len(ast.children[0].children))

        self.assertIsInstance(ast.children[0].children[0], TemplateNode)
        self.assertIsInstance(ast.children[0].children[1], TemplateNode)
        self.assertIsInstance(ast.children[0].children[2], TemplateNode)

        selection = ast.children[0].resolve(self.test_bot, self.test_clientid)
        self.assertIsNotNone(selection)
        self.assertIn(selection, ['1', '2', '3'])

    def test_random_nested_template(self):
        template = ET.fromstring("""
			<template>
				<random>
					<li>
						<random>
							<li>Say something</li>
							<li>Say the other</li>
						</random>
					</li>
					<li>
						<random>
							<li>Hello world!</li>
							<li>Goodbye cruel world</li>
						</random>
					</li>
				</random>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)

        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)
        self.assertIsNotNone(ast.children[0])
        self.assertIsInstance(ast.children[0], TemplateRandomNode)
        self.assertEqual(2, len(ast.children[0].children))

        self.assertIsInstance(ast.children[0].children[0], TemplateNode)
        self.assertEqual(1, len(ast.children[0].children[0].children))
        self.assertIsInstance(ast.children[0].children[0].children[0], TemplateRandomNode)
        self.assertEqual(2, len(ast.children[0].children[0].children[0].children))

        self.assertIsInstance(ast.children[0].children[1], TemplateNode)
        self.assertEqual(1, len(ast.children[0].children[1].children))
        self.assertIsInstance(ast.children[0].children[1].children[0], TemplateRandomNode)
        self.assertEqual(2, len(ast.children[0].children[1].children[0].children))

        selection = ast.children[0].resolve(self.test_bot, self.test_clientid)
        self.assertIsNotNone(selection)
        self.assertIn(selection, ['Say something', 'Say the other', 'Hello world!', 'Goodbye cruel world'])
示例#11
0
class TemplateGraphTransformsTests(unittest.TestCase):
    def setUp(self):
        self.parser = TemplateGraph()
        self.assertIsNotNone(self.parser)

        self.test_brain = None
        self.test_sentence = Sentence("test sentence")
        self.test_sentence._stars = [
            'one', 'two', 'three', 'four', 'five', 'six'
        ]
        self.test_sentence._thatstars = ["*"]
        self.test_sentence._topicstars = ["*"]

        test_config = ClientConfiguration()

        self.test_bot = Bot(Brain(BrainConfiguration()),
                            config=test_config.bot_configuration)
        self.test_clientid = "testid"

        conversation = self.test_bot.get_conversation(self.test_clientid)
        question = Question.create_from_sentence(self.test_sentence)
        conversation._questions.append(question)

    def test_lowercase(self):
        template = ET.fromstring("""
            <template>
                <lowercase>This is a Sentence</lowercase>
            </template>
            """)
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertEqual(ast.resolve(None, None), "this is a sentence")

    def test_uppercase(self):
        template = ET.fromstring("""
            <template>
                <uppercase>This is a Sentence</uppercase>
            </template>
            """)
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertEqual(ast.resolve(None, None), "THIS IS A SENTENCE")

    def test_formal(self):
        template = ET.fromstring("""
            <template>
                <formal>This is a Sentence</formal>
            </template>
            """)
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertEqual(ast.resolve(None, None), "This Is A Sentence")

    def test_sentence(self):
        template = ET.fromstring("""
            <template>
                <sentence>This is a Sentence</sentence>
            </template>
            """)
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertEqual(ast.resolve(None, None), "This is a sentence")

    def test_normalize(self):
        template = ET.fromstring("""
			<template>
				<normalize>XYZ</normalize>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)

    def test_denormalize(self):
        template = ET.fromstring("""
			<template>
				<denormalize>XYZ</denormalize>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)

    def test_person(self):
        template = ET.fromstring("""
			<template>
				<person>XYZ</person>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)

    def test_person2(self):
        template = ET.fromstring("""
			<template>
				<person2>XYZ</person2>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)

    def test_gender(self):
        template = ET.fromstring("""
			<template>
				<gender>XYZ</gender>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)

    def test_sr(self):
        template = ET.fromstring("""
			<template>
				<sr>XYZ</sr>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)

    def test_id(self):
        template = ET.fromstring("""
			<template>
				<id />
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertEqual(ast.resolve(None, "clientid"), "clientid")

    def test_vocabulary(self):
        template = ET.fromstring("""
			<template>
				<vocabulary>XYZ</vocabulary>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)

    def test_program(self):
        template = ET.fromstring("""
			<template>
				<program>XYZ</program>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)

    def test_explode(self):
        template = ET.fromstring("""
			<template>
				<explode>XYZ</explode>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertEqual(ast.resolve(None, None), "X Y Z")

    def test_implode(self):
        template = ET.fromstring("""
			<template>
				<implode>X Y Z</implode>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertEqual(ast.resolve(None, None), "XYZ")
示例#12
0
class AIMLParser(object):
    def __init__(self, brain=None):
        self._brain = brain
        self.pattern_parser = PatternGraph(aiml_parser=self)
        self.template_parser = TemplateGraph(aiml_parser=self)
        self._aiml_loader = AIMLLoader(self)
        self._num_categories = 0
        self._duplicates = None
        self._errors = None

    @property
    def brain(self):
        return self._brain

    @property
    def num_categories(self):
        return self._num_categories

    def create_debug_storage(self, brain_configuration):
        if brain_configuration.files.aiml_files.errors is not None:
            self._errors = []
        if brain_configuration.files.aiml_files.duplicates is not None:
            self._duplicates = []

    def save_debug_files(self, brain_configuration):

        if brain_configuration.files.aiml_files.errors is not None:
            if logging.getLogger().isEnabledFor(logging.INFO):
                logging.info("Saving aiml errors to file [%s]",
                             brain_configuration.files.aiml_files.errors)
            try:
                with open(brain_configuration.files.aiml_files.errors,
                          "w+") as errors_file:
                    for error in self._errors:
                        errors_file.write(error)
            except Exception as excep:
                logging.exception(excep)

        if brain_configuration.files.aiml_files.duplicates is not None:
            if logging.getLogger().isEnabledFor(logging.INFO):
                logging.info("Saving aiml duplicates to file [%s]",
                             brain_configuration.files.aiml_files.duplicates)
            try:
                with open(brain_configuration.files.aiml_files.duplicates,
                          "w+") as duplicates_file:
                    for duplicate in self._duplicates:
                        duplicates_file.write(duplicate)
            except Exception as excep:
                logging.exception(excep)

    def display_debug_info(self, brain_configuration):
        if self._errors is not None:
            if logging.getLogger().isEnabledFor(logging.INFO):
                logging.info(
                    "Found a total of %d errors in your grammrs, check out [%s] for details",
                    len(self._errors),
                    brain_configuration.files.aiml_files.errors)
        if self._duplicates is not None:
            if logging.getLogger().isEnabledFor(logging.INFO):
                logging.info(
                    "Found a total of %d duplicate patterns in your grammrs, check out [%s] for details",
                    len(self._duplicates),
                    brain_configuration.files.aiml_files.duplicates)

    def load_files_from_directory(self, brain_configuration):
        start = datetime.datetime.now()
        total_aimls_loaded = 0
        for file in brain_configuration.files.aiml_files.files:
            aimls_loaded = self._aiml_loader.load_dir_contents(
                file, brain_configuration.files.aiml_files.directories,
                brain_configuration.files.aiml_files.extension)
            total_aimls_loaded = len(aimls_loaded)
        stop = datetime.datetime.now()
        diff = stop - start
        if logging.getLogger().isEnabledFor(logging.INFO):
            logging.info("Total processing time %.6f secs",
                         diff.total_seconds())
            logging.info("Loaded a total of %d aiml files with %d categories",
                         total_aimls_loaded, self.num_categories)
        if diff.total_seconds() > 0:
            if logging.getLogger().isEnabledFor(logging.INFO):
                logging.info("Thats approx %f aiml files per sec",
                             total_aimls_loaded / diff.total_seconds())

    def load_single_file(self, brain_configuration):
        start = datetime.datetime.now()
        self._aiml_loader.load_single_file_contents(
            brain_configuration.files.aiml_files.file)
        stop = datetime.datetime.now()
        diff = stop - start
        if logging.getLogger().isEnabledFor(logging.INFO):
            logging.info("Total processing time %.6f secs",
                         diff.total_seconds())
            logging.info("Loaded a single aiml file with %d categories",
                         self.num_categories)

    def load_aiml(self, brain_configuration: BrainConfiguration):

        if brain_configuration.files.aiml_files is not None:

            self.create_debug_storage(brain_configuration)

            if brain_configuration.files.aiml_files.has_multiple_files():
                self.load_files_from_directory(brain_configuration)

            elif brain_configuration.files.aiml_files.has_single_file():
                self.load_single_file(brain_configuration)

            else:
                if logging.getLogger().isEnabledFor(logging.INFO):
                    logging.info(
                        "No AIML files or file defined in configuration to load"
                    )

            self.save_debug_files(brain_configuration)

            self.display_debug_info(brain_configuration)

        else:
            if logging.getLogger().isEnabledFor(logging.INFO):
                logging.info(
                    "No AIML files or file defined in configuration to load")

    def tag_and_namespace_from_text(self, text):
        # If there is a namespace, then it looks something like
        # {http://alicebot.org/2001/AIML}aiml
        pattern = re.compile("^{.*}.*$")
        if pattern.match(text) is None:
            # If that pattern does not exist, assume that the text is the tag name
            return text, None

        # Otherwise, extract namespace and tag name
        match = re.compile("^({.*})(.*)$")
        groupings = match.match(text)
        if groupings is not None:
            namespace = groupings.group(1).strip()
            tag_name = groupings.group(2).strip()
            return tag_name, namespace
        return None, None

    def tag_from_text(self, text):
        tag, _ = self.tag_and_namespace_from_text(text)
        return tag

    def check_aiml_tag(self, aiml, filename=None):
        # Null check just to be sure
        if aiml is None:
            raise ParserException("Error, null root tag", filename=filename)

        tag_name, namespace = self.tag_and_namespace_from_text(aiml.tag)

        # Then if check is just <aiml>, thats OK
        if tag_name != 'aiml':
            raise ParserException("Error, root tag is not <aiml>",
                                  filename=filename)

        return tag_name, namespace

    def parse_from_file(self, filename):
        """
        Parse an AIML file and return all the cateogeries found in the file
        :param filename: Name of file to parse
        :return list of categories parsed from file:
        """
        if logging.getLogger().isEnabledFor(logging.INFO):
            logging.info("Loading aiml file: " + filename)

        try:
            tree = ET.parse(filename, parser=LineNumberingParser())
            aiml = tree.getroot()

            _, namespace = self.check_aiml_tag(aiml, filename=filename)

            start = datetime.datetime.now()
            num_categories = self.parse_aiml(aiml, namespace, filename)
            stop = datetime.datetime.now()
            diff = stop - start
            if logging.getLogger().isEnabledFor(logging.INFO):
                logging.info("Processed %s with %d categories in %f.2 secs",
                             filename, num_categories, diff.total_seconds())

        except Exception as excep:
            logging.exception(excep)
            if logging.getLogger().isEnabledFor(logging.ERROR):
                logging.error(
                    "Failed to load contents of AIML file from [%s] - [%s]",
                    filename, excep)

    def parse_from_text(self, text):
        """
         Parse an AIML text version of an aiml file and return all the cateogeries found in the file
         :param text: Fully validated AIML snippet
         :return list of categories parsed from file:
         """

        aiml = ET.fromstring(text)

        _, namespace = self.check_aiml_tag(aiml)

        self.parse_aiml(aiml, namespace)

    #########################################################################################
    #
    #   <?xml version = "1.0" encoding = "UTF-8"?>
    #   <aiml>
    #       <category>
    #           :
    #       </category>
    #       <topic>
    #           <category>
    #           :
    #           </category>
    #       </topic>
    #   </aiml>
    #

    def handle_aiml_duplicate(self, dupe_excep, filename, expression):
        if self._duplicates is not None:
            dupe_excep.filename = filename
            msg = dupe_excep.format_message()
            if hasattr(expression, "_start_line_number"):
                msg += " start line [" + str(
                    expression._start_line_number) + "] "
            if hasattr(expression, "_end_line_number"):
                msg += " end line [" + str(expression._end_line_number) + "] "
            msg += "\n"
            if logging.getLogger().isEnabledFor(logging.ERROR):
                logging.error(msg)
            if self._duplicates is not None:
                self._duplicates.append(msg)

    def handle_aiml_error(self, parser_excep, filename, expression):
        parser_excep.filename = filename
        msg = parser_excep.format_message()
        if hasattr(expression, "_start_line_number"):
            msg += " start line [" + str(expression._start_line_number) + "] "
        if hasattr(expression, "_end_line_number"):
            msg += " end line [" + str(expression._end_line_number) + "] "
        msg += "\n"
        if logging.getLogger().isEnabledFor(logging.ERROR):
            logging.error(msg)
        if self._errors is not None:
            self._errors.append(msg)

    def parse_aiml(self, aiml_xml, namespace, filename=None):
        self.parse_version(aiml_xml)

        categories_found = False
        num_category = 0
        for expression in aiml_xml:
            tag_name, namespace = self.tag_and_namespace_from_text(
                expression.tag)
            if tag_name == 'topic':
                try:
                    num_topic_categories = self.parse_topic(
                        expression, namespace)
                    num_category += num_topic_categories
                    categories_found = True

                except DuplicateGrammarException as dupe_excep:
                    self.handle_aiml_duplicate(dupe_excep, filename,
                                               expression)

                except ParserException as parser_excep:
                    self.handle_aiml_error(parser_excep, filename, expression)

            elif tag_name == 'category':
                try:
                    self.parse_category(expression, namespace)
                    categories_found = True
                    num_category += 1

                except DuplicateGrammarException as dupe_excep:
                    self.handle_aiml_duplicate(dupe_excep, filename,
                                               expression)

                except ParserException as parser_excep:
                    self.handle_aiml_error(parser_excep, filename, expression)

            else:
                raise ParserException("Error, unknown top level tag, %s" %
                                      expression.tag,
                                      xml_element=expression)

        if categories_found is False:
            if logging.getLogger().isEnabledFor(logging.WARNING):
                logging.warning("no categories in aiml file")

        return num_category

    #########################################################################################
    #
    # AIML_VERSION ::== 0.9 | 1.0 | 1.1 | 2.0
    #

    def parse_version(self, aiml):
        if 'version' in aiml.attrib:
            version = aiml.attrib['version']
            if version not in ['0.9', '1.0', '1.1', '2.0']:
                if logging.getLogger().isEnabledFor(logging.WARNING):
                    logging.warning(
                        "Version number not a supported version: %s", version)
        else:
            if logging.getLogger().isEnabledFor(logging.WARNING):
                logging.warning("No version info, defaulting to 2.0")
            version = "2.0"
        return version

    #########################################################################################
    #
    # TOPIC_EXPRESSION:: == <topic name = "PATTERN_EXPRESSION" > (CATEGORY_EXPRESSION) + < / topic >
    #
    # PATTERN_EXPRESSION:: == WORD | PRIORITY_WORD | WILDCARD | SET_STATEMENT | PATTERN_SIDE_BOT_PROPERTY_EXPRESSION
    # PATTERN_EXPRESSION:: == PATTERN_EXPRESSION PATTERN_EXPRESSION
    #
    # This means both topic and that can also be a set of words, stars, hash, sets and bots
    #
    # CATEGORY_EXPRESSION:: == <category>
    #                               <pattern> PATTERN_EXPRESSION </pattern>
    #                              (<that> PATTERN_EXPRESSION </that>)
    #                              (<topic> PATTERN_EXPRESSION </topic>)
    #                              < template > TEMPLATE_EXPRESSION < / template >
    #                          </category>

    def parse_topic(self, topic_element, namespace):

        if 'name' in topic_element.attrib:
            name = topic_element.attrib['name']
            if name is None or not name:
                raise ParserException("Topic name empty or null",
                                      xml_element=topic_element)
            xml = "<topic>%s</topic>" % name
            if logging.getLogger().isEnabledFor(logging.INFO):
                logging.info("Topic attrib converted to %s", xml)
            topic_pattern = ET.fromstring(xml)
        else:
            raise ParserException("Error, missing name attribute for topic",
                                  xml_element=topic_element)

        category_found = False
        num_category = 0
        for child in topic_element:
            tag_name, _ = self.tag_and_namespace_from_text(child.tag)
            if tag_name == 'category':
                self.parse_category(child, namespace, topic_pattern)
                category_found = True
                num_category += 1
            else:
                raise ParserException("Error unknown child node of topic, %s" %
                                      child.tag,
                                      xml_element=topic_element)

        if category_found is False:
            raise ParserException("Error, no categories in topic",
                                  xml_element=topic_element)

        return num_category

    def find_all(self, element, name, namespace):
        if namespace is not None:
            search = '%s%s' % (namespace, name)
            return element.findall(search)
        return element.findall(name)

    def find_topic(self, category_xml, namespace, topic_element=None):
        topics = self.find_all(category_xml, "topic", namespace)

        if topic_element is not None:
            if topics:
                raise ParserException(
                    "Error, topic exists in category AND as parent node",
                    xml_element=category_xml)

        else:
            if len(topics) > 1:
                raise ParserException(
                    "Error, multiple <topic> nodes found in category",
                    xml_element=category_xml)
            elif len(topics) == 1:
                topic_element = topics[0]
            else:
                topic_element = ET.fromstring("<topic>*</topic>")

        return topic_element

    def find_that(self, category_xml, namespace):
        thats = self.find_all(category_xml, "that", namespace)
        if len(thats) > 1:
            raise ParserException(
                "Error, multiple <that> nodes found in category",
                xml_element=category_xml)
        elif len(thats) == 1:
            that_element = thats[0]
        else:
            that_element = ET.fromstring("<that>*</that>")
        return that_element

    def get_template(self, category_xml, namespace):
        templates = self.find_all(category_xml, "template", namespace)
        if not templates:
            raise ParserException("Error, no template node found in category",
                                  xml_element=category_xml)
        elif len(templates) > 1:
            raise ParserException(
                "Error, multiple <template> nodes found in category",
                xml_element=category_xml)
        else:
            return self.template_parser.parse_template_expression(templates[0])

    def get_pattern(self, category_xml, namespace):
        patterns = self.find_all(category_xml, "pattern", namespace)
        if not patterns:
            raise ParserException("Error, no pattern node found in category",
                                  xml_element=category_xml)
        elif len(patterns) > 1:
            raise ParserException(
                "Error, multiple <pattern> nodes found in category",
                xml_element=category_xml)
        else:
            return patterns[0]

    def parse_category(self,
                       category_xml,
                       namespace,
                       topic_element=None,
                       add_to_graph=True):

        topic_element = self.find_topic(category_xml, namespace, topic_element)

        that_element = self.find_that(category_xml, namespace)

        template_graph_root = self.get_template(category_xml, namespace)

        pattern = self.get_pattern(category_xml, namespace)

        if add_to_graph is True:
            self.pattern_parser.add_pattern_to_graph(pattern, topic_element,
                                                     that_element,
                                                     template_graph_root)
            self._num_categories += 1

        return (pattern, topic_element, that_element, template_graph_root)

    def match_sentence(self, bot, clientid, pattern_sentence, topic_pattern,
                       that_pattern):

        topic_sentence = Sentence(topic_pattern)
        that_sentence = Sentence(that_pattern)

        if logging.getLogger().isEnabledFor(logging.DEBUG):
            logging.debug(
                "AIML Parser matching sentence [%s], topic=[%s], that=[%s] ",
                pattern_sentence.text(), topic_pattern, that_pattern)

        sentence = Sentence()
        sentence.append_sentence(pattern_sentence)
        sentence.append_word('__TOPIC__')
        sentence.append_sentence(topic_sentence)
        sentence.append_word('__THAT__')
        sentence.append_sentence(that_sentence)
        if logging.getLogger().isEnabledFor(logging.DEBUG):
            logging.debug("Matching [%s]", sentence.words_from_current_pos(0))

        context = MatchContext(
            max_search_depth=bot.configuration.max_search_depth,
            max_search_timeout=bot.configuration.max_search_timeout)

        template = self.pattern_parser._root_node.match(
            bot, clientid, context, sentence)

        if template is not None:
            context._template_node = template

            context.list_matches()

            # Save the matched context for the associated sentence
            pattern_sentence.matched_context = context

            return context

        return None
示例#13
0
class TemplateGraphConditionTests(unittest.TestCase):
    def setUp(self):
        self.parser = TemplateGraph()
        self.assertIsNotNone(self.parser)

        self.test_brain = None
        self.test_sentence = Sentence("test sentence")
        self.test_sentence._stars = [
            'one', 'two', 'three', 'four', 'five', 'six'
        ]
        self.test_sentence._thatstars = ["*"]
        self.test_sentence._topicstars = ["*"]

        test_config = ClientConfiguration()

        self.test_bot = Bot(Brain(BrainConfiguration()),
                            config=test_config.bot_configuration)
        self.test_clientid = "testid"

        conversation = self.test_bot.get_conversation(self.test_clientid)
        question = Question.create_from_sentence(self.test_sentence)
        conversation._questions.append(question)

    def test_condition_template_no_attribs(self):
        template = ET.fromstring("""
			<template>
				<condition>
				</condition>
			</template>
			""")
        with self.assertRaises(ParserException):
            self.parser.parse_template_expression(template)

    def test_condition_template_type1_variant1_name(self):
        template = ET.fromstring("""
			<template>
				<condition name="aname" value="avalue">X <random><li>1</li><li>2</li></random> Y</condition>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)

        template_node = ast.children[0]
        self.assertIsNotNone(template_node)
        self.assertIsInstance(template_node, TemplateType1ConditionNode)

        self.assertFalse(template_node.local)
        self.assertEqual(template_node.name, "aname")
        self.assertEqual(template_node.value, "avalue")

        self.assertEqual(len(template_node.children), 3)

    def test_condition_template_type1_variant1_var(self):
        template = ET.fromstring("""
            <template>
                <condition var="aname" value="avalue">X <random><li>1</li><li>2</li></random> Y</condition>
            </template>
            """)
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)

        template_node = ast.children[0]
        self.assertIsNotNone(template_node)
        self.assertIsInstance(template_node, TemplateType1ConditionNode)

        self.assertTrue(template_node.local)
        self.assertEqual(template_node.name, "aname")
        self.assertEqual(template_node.value, "avalue")

        self.assertEqual(len(template_node.children), 3)

    def test_condition_template_type1_variant2_name(self):
        template = ET.fromstring("""
			<template>
				<condition name="aname"><value>avalue</value>X</condition>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)

        template_node = ast.children[0]
        self.assertIsNotNone(template_node)
        self.assertIsInstance(template_node, TemplateType1ConditionNode)

        self.assertFalse(template_node.local)
        self.assertEqual(template_node.name, "aname")
        self.assertEqual(template_node.value, "avalue")

        self.assertEqual(len(template_node.children), 1)

    def test_condition_template_type1_variant2_var(self):
        template = ET.fromstring("""
            <template>
                <condition var="aname"><value>avalue</value>X</condition>
            </template>
            """)
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)

        template_node = ast.children[0]
        self.assertIsNotNone(template_node)
        self.assertIsInstance(template_node, TemplateType1ConditionNode)

        self.assertTrue(template_node.local)
        self.assertEqual(template_node.name, "aname")
        self.assertEqual(template_node.value, "avalue")

        self.assertEqual(len(template_node.children), 1)

    def test_condition_template_type1_variant3_name(self):
        template = ET.fromstring("""
			<template>
				<condition value="avalue"><name>aname</name>X</condition>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)

        template_node = ast.children[0]
        self.assertIsNotNone(template_node)
        self.assertIsInstance(template_node, TemplateType1ConditionNode)
        self.assertFalse(template_node.local)
        self.assertEqual(template_node.name, "aname")
        self.assertEqual(template_node.value, "avalue")

        self.assertEqual(len(template_node.children), 1)

    def test_condition_template_type1_variant3_var(self):
        template = ET.fromstring("""
            <template>
                <condition value="avalue"><var>aname</var>X</condition>
            </template>
            """)
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)

        template_node = ast.children[0]
        self.assertIsNotNone(template_node)
        self.assertIsInstance(template_node, TemplateType1ConditionNode)

        self.assertTrue(template_node.local)
        self.assertEqual(template_node.name, "aname")
        self.assertEqual(template_node.value, "avalue")

        self.assertEqual(len(template_node.children), 1)

    def test_condition_template_type1_variant4_name(self):
        template = ET.fromstring("""
			<template>
				<condition><name>aname</name><value>avalue</value>X</condition>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)

        template_node = ast.children[0]
        self.assertIsNotNone(template_node)
        self.assertIsInstance(template_node, TemplateType1ConditionNode)

        self.assertFalse(template_node.local)
        self.assertEqual(template_node.name, "aname")
        self.assertEqual(template_node.value, "avalue")

        self.assertEqual(len(template_node.children), 1)

    def test_condition_template_type1_variant4_var(self):
        template = ET.fromstring("""
            <template>
                <condition><var>aname</var><value>avalue</value>X</condition>
            </template>
            """)
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)

        template_node = ast.children[0]
        self.assertIsNotNone(template_node)
        self.assertIsInstance(template_node, TemplateType1ConditionNode)

        self.assertTrue(template_node.local)
        self.assertEqual(template_node.name, "aname")
        self.assertEqual(template_node.value, "avalue")

        self.assertEqual(len(template_node.children), 1)

    def test_condition_template_type2_variant1_name(self):
        template = ET.fromstring("""
			<template>
				<condition>
					<name>aname</name>
					<li value="a">A</li>
					<li value="b">B</li>
					<li><value>c</value>C</li>
					<li>D</li>
				</condition>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)

        template_node = ast.children[0]
        self.assertIsNotNone(template_node)
        self.assertIsInstance(template_node, TemplateType2ConditionNode)
        self.assertFalse(template_node.local)
        self.assertEqual(template_node.name, "aname")
        self.assertEqual(len(template_node.children), 4)

        node = template_node.children[0]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertFalse(node.local)
        self.assertFalse(node.loop)
        self.assertIsNone(node.name)
        self.assertEqual(node.value, "a")
        self.assertFalse(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "A")

        node = template_node.children[1]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertFalse(node.local)
        self.assertFalse(node.loop)
        self.assertIsNone(node.name)
        self.assertEqual(node.value, "b")
        self.assertFalse(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "B")

        node = template_node.children[2]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertFalse(node.local)
        self.assertFalse(node.loop)
        self.assertIsNone(node.name)
        self.assertEqual(node.value, "c")
        self.assertFalse(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "C")

        node = template_node.children[3]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertFalse(node.local)
        self.assertFalse(node.loop)
        self.assertIsNone(node.name)
        self.assertIsNone(node.value)
        self.assertTrue(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "D")

    def test_condition_template_type2_variant1_name_with_loop(self):
        template = ET.fromstring("""
            <template>
                <condition>
                    <name>aname</name>
                    <li value="a">A <loop /></li>
                    <li value="b">B</li>
                    <li><value>c</value>C</li>
                    <li>D</li>
                </condition>
            </template>
            """)
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)

        template_node = ast.children[0]
        self.assertIsNotNone(template_node)
        self.assertIsInstance(template_node, TemplateType2ConditionNode)
        self.assertFalse(template_node.local)
        self.assertEqual(template_node.name, "aname")
        self.assertEqual(len(template_node.children), 4)

        node = template_node.children[0]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertFalse(node.local)
        self.assertTrue(node.loop)
        self.assertIsNone(node.name)
        self.assertEqual(node.value, "a")
        self.assertFalse(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "A")

        node = template_node.children[1]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertFalse(node.local)
        self.assertFalse(node.loop)
        self.assertIsNone(node.name)
        self.assertEqual(node.value, "b")
        self.assertFalse(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "B")

        node = template_node.children[2]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertFalse(node.local)
        self.assertFalse(node.loop)
        self.assertIsNone(node.name)
        self.assertEqual(node.value, "c")
        self.assertFalse(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "C")

        node = template_node.children[3]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertFalse(node.local)
        self.assertFalse(node.loop)
        self.assertIsNone(node.name)
        self.assertIsNone(node.value)
        self.assertTrue(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "D")

    def test_condition_template_type2_variant1_var(self):
        template = ET.fromstring("""
            <template>
                <condition>
                    <var>aname</var>
                    <li value="a">A</li>
                    <li value="b">B</li>
                    <li><value>c</value>C</li>
                    <li>D</li>
                </condition>
            </template>
            """)
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)

        template_node = ast.children[0]
        self.assertIsNotNone(template_node)
        self.assertIsInstance(template_node, TemplateType2ConditionNode)
        self.assertTrue(template_node.local)
        self.assertEqual(template_node.name, "aname")
        self.assertEqual(len(template_node.children), 4)

        node = template_node.children[0]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertTrue(node.local)
        self.assertFalse(node.loop)
        self.assertIsNone(node.name)
        self.assertEqual(node.value, "a")
        self.assertFalse(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "A")

        node = template_node.children[1]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertTrue(node.local)
        self.assertFalse(node.loop)
        self.assertIsNone(node.name)
        self.assertEqual(node.value, "b")
        self.assertFalse(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "B")

        node = template_node.children[2]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertTrue(node.local)
        self.assertFalse(node.loop)
        self.assertIsNone(node.name)
        self.assertEqual(node.value, "c")
        self.assertFalse(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "C")

        node = template_node.children[3]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertTrue(node.local)
        self.assertFalse(node.loop)
        self.assertIsNone(node.name)
        self.assertIsNone(node.value)
        self.assertTrue(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "D")

    def test_condition_template_type2_variant2_name(self):
        template = ET.fromstring("""
			<template>
				<condition name="aname">
					<li value="a">A</li>
					<li value="b">B</li>
					<li><value>c</value>C</li>
					<li>D</li>
				</condition>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)

        template_node = ast.children[0]
        self.assertIsNotNone(template_node)
        self.assertIsInstance(template_node, TemplateType2ConditionNode)
        self.assertFalse(template_node.local)
        self.assertEqual(template_node.name, "aname")
        self.assertEqual(len(template_node.children), 4)

        node = template_node.children[0]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertFalse(node.local)
        self.assertFalse(node.loop)
        self.assertIsNone(node.name)
        self.assertEqual(node.value, "a")
        self.assertFalse(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "A")

        node = template_node.children[1]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertFalse(node.local)
        self.assertFalse(node.loop)
        self.assertIsNone(node.name)
        self.assertEqual(node.value, "b")
        self.assertFalse(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "B")

        node = template_node.children[2]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertFalse(node.local)
        self.assertFalse(node.loop)
        self.assertIsNone(node.name)
        self.assertEqual(node.value, "c")
        self.assertFalse(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "C")

        node = template_node.children[3]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertFalse(node.local)
        self.assertFalse(node.loop)
        self.assertIsNone(node.name)
        self.assertIsNone(node.value)
        self.assertTrue(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "D")

    def test_condition_template_type2_variant2_var(self):
        template = ET.fromstring("""
            <template>
                <condition var="aname">
                    <li value="a">A</li>
                    <li value="b">B</li>
                    <li><value>c</value>C</li>
                    <li>D</li>
                </condition>
            </template>
            """)
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)

        template_node = ast.children[0]
        self.assertIsNotNone(template_node)
        self.assertIsInstance(template_node, TemplateType2ConditionNode)
        self.assertTrue(template_node.local)
        self.assertEqual(template_node.name, "aname")
        self.assertEqual(len(template_node.children), 4)

        node = template_node.children[0]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertTrue(node.local)
        self.assertFalse(node.loop)
        self.assertIsNone(node.name)
        self.assertEqual(node.value, "a")
        self.assertFalse(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "A")

        node = template_node.children[1]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertTrue(node.local)
        self.assertFalse(node.loop)
        self.assertIsNone(node.name)
        self.assertEqual(node.value, "b")
        self.assertFalse(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "B")

        node = template_node.children[2]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertTrue(node.local)
        self.assertFalse(node.loop)
        self.assertIsNone(node.name)
        self.assertEqual(node.value, "c")
        self.assertFalse(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "C")

        node = template_node.children[3]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertTrue(node.local)
        self.assertFalse(node.loop)
        self.assertIsNone(node.name)
        self.assertIsNone(node.value)
        self.assertTrue(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "D")

    def test_condition_template_type3_variant1_name(self):
        template = ET.fromstring("""
			<template>
				<condition>
					<li name='name1' value="a">Val1</li>
					<li value="b"><name>name2</name>Val2</li>
					<li name="name3"><value>c</value>Val3</li>
					<li><name>name4</name><value>d</value>Val4</li>
					<li>Val5</li>
				</condition>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)

        template_node = ast.children[0]

        self.assertIsNotNone(template_node)
        self.assertIsInstance(template_node, TemplateType3ConditionNode)
        self.assertEqual(len(template_node.children), 5)

        node = template_node.children[0]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertFalse(node.local)
        self.assertFalse(node.loop)
        self.assertIsNotNone(node.name)
        self.assertEqual(node.name, "name1")
        self.assertIsNotNone(node.value)
        self.assertEqual(node.value, "a")
        self.assertFalse(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "Val1")

        node = template_node.children[1]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertFalse(node.local)
        self.assertFalse(node.loop)
        self.assertIsNotNone(node.name)
        self.assertEqual(node.name, "name2")
        self.assertIsNotNone(node.value)
        self.assertEqual(node.value, "b")
        self.assertFalse(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "Val2")

        node = template_node.children[2]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertFalse(node.local)
        self.assertFalse(node.loop)
        self.assertIsNotNone(node.name)
        self.assertEqual(node.name, "name3")
        self.assertIsNotNone(node.value)
        self.assertEqual(node.value, "c")
        self.assertFalse(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "Val3")

        node = template_node.children[3]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertFalse(node.local)
        self.assertFalse(node.loop)
        self.assertEqual(node.name, "name4")
        self.assertIsNotNone(node.value)
        self.assertEqual(node.value, "d")
        self.assertFalse(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "Val4")

        node = template_node.children[4]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertFalse(node.local)
        self.assertFalse(node.loop)
        self.assertIsNone(node.name)
        self.assertIsNone(node.value)
        self.assertTrue(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "Val5")

    def test_condition_template_type3_variant1_name_with_loop(self):
        template = ET.fromstring("""
            <template>
                <condition>
                    <li name='name1' value="a">Val1 <loop /></li>
                    <li value="b"><name>name2</name>Val2</li>
                    <li name="name3"><value>c</value>Val3</li>
                    <li><name>name4</name><value>d</value>Val4</li>
                    <li>Val5</li>
                </condition>
            </template>
            """)
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)

        template_node = ast.children[0]

        self.assertIsNotNone(template_node)
        self.assertIsInstance(template_node, TemplateType3ConditionNode)
        self.assertEqual(len(template_node.children), 5)

        node = template_node.children[0]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertFalse(node.local)
        self.assertTrue(node.loop)
        self.assertIsNotNone(node.name)
        self.assertEqual(node.name, "name1")
        self.assertIsNotNone(node.value)
        self.assertEqual(node.value, "a")
        self.assertFalse(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "Val1")

        node = template_node.children[1]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertFalse(node.local)
        self.assertFalse(node.loop)
        self.assertIsNotNone(node.name)
        self.assertEqual(node.name, "name2")
        self.assertIsNotNone(node.value)
        self.assertEqual(node.value, "b")
        self.assertFalse(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "Val2")

        node = template_node.children[2]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertFalse(node.local)
        self.assertFalse(node.loop)
        self.assertIsNotNone(node.name)
        self.assertEqual(node.name, "name3")
        self.assertIsNotNone(node.value)
        self.assertEqual(node.value, "c")
        self.assertFalse(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "Val3")

        node = template_node.children[3]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertFalse(node.local)
        self.assertFalse(node.loop)
        self.assertEqual(node.name, "name4")
        self.assertIsNotNone(node.value)
        self.assertEqual(node.value, "d")
        self.assertFalse(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "Val4")

        node = template_node.children[4]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertFalse(node.local)
        self.assertFalse(node.loop)
        self.assertIsNone(node.name)
        self.assertIsNone(node.value)
        self.assertTrue(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "Val5")

    def test_condition_template_type3_variant1_var(self):
        template = ET.fromstring("""
			<template>
				<condition>
					<li var='name1' value="a">Val1</li>
					<li value="b"><var>name2</var>Val2</li>
					<li var="name3"><value>c</value>Val3</li>
					<li><var>name4</var><value>d</value>Val4</li>
					<li>Val5</li>
				</condition>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)

        template_node = ast.children[0]

        self.assertIsNotNone(template_node)
        self.assertIsInstance(template_node, TemplateType3ConditionNode)
        self.assertEqual(len(template_node.children), 5)

        node = template_node.children[0]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertTrue(node.local)
        self.assertFalse(node.loop)
        self.assertIsNotNone(node.name)
        self.assertEqual(node.name, "name1")
        self.assertIsNotNone(node.value)
        self.assertEqual(node.value, "a")
        self.assertFalse(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "Val1")

        node = template_node.children[1]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertTrue(node.local)
        self.assertFalse(node.loop)
        self.assertIsNotNone(node.name)
        self.assertEqual(node.name, "name2")
        self.assertIsNotNone(node.value)
        self.assertEqual(node.value, "b")
        self.assertFalse(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "Val2")

        node = template_node.children[2]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertTrue(node.local)
        self.assertFalse(node.loop)
        self.assertIsNotNone(node.name)
        self.assertEqual(node.name, "name3")
        self.assertIsNotNone(node.value)
        self.assertEqual(node.value, "c")
        self.assertFalse(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "Val3")

        node = template_node.children[3]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertTrue(node.local)
        self.assertFalse(node.loop)
        self.assertIsNotNone(node.name)
        self.assertEqual(node.name, "name4")
        self.assertIsNotNone(node.value)
        self.assertEqual(node.value, "d")
        self.assertFalse(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "Val4")

        node = template_node.children[4]
        self.assertIsInstance(node, TemplateConditionListItemNode)
        self.assertFalse(node.local)
        self.assertFalse(node.loop)
        self.assertIsNone(node.name)
        self.assertIsNone(node.value)
        self.assertTrue(node.is_default())
        self.assertEqual(len(node.children), 1)
        self.assertEqual(node.children[0].resolve(None, None), "Val5")
示例#14
0
class AIMLParser(object):
    def __init__(self, supress_warnings=False, stop_on_invalid=False):
        self._supress_warnings = supress_warnings
        self.stop_on_invalid = stop_on_invalid
        self.pattern_parser = PatternGraph()
        self.template_parser = TemplateGraph(self)
        self._filename = "Unknown"
        self._version = "Unknown"
        self._aiml_loader = AIMLLoader(self)
        self._num_categories = 0

    @property
    def supress_warnings(self):
        return self._supress_warnings

    @property
    def num_categories(self):
        return self._num_categories

    def load_aiml(self, brain_configuration: BrainConfiguration):
        self._supress_warnings = brain_configuration.supress_warnings
        if brain_configuration.aiml_files is not None:
            aimls_loaded = self._aiml_loader.load_dir_contents(
                brain_configuration.aiml_files.files,
                brain_configuration.aiml_files.directories,
                brain_configuration.aiml_files.extension)
            logging.info("Loaded a total of %d aiml files", len(aimls_loaded))
        else:
            logging.info("No AIML files defined in configuration to load")

    def parse_from_file(self, filename):
        """
        Parse an AIML file and return all the cateogeries found in the file
        :param filename: Name of file to parse
        :return list of categories parsed from file:
        """
        self._filename = filename

        logging.info("Loading aiml file file: " + self._filename)

        tree = ET.parse(filename, parser=LineNumberingParser())
        aiml = tree.getroot()

        if aiml is None or aiml.tag != 'aiml':
            raise ParserException("Error, root tag is not <aiml>",
                                  filename=filename)
        else:
            try:
                self.parse_aiml(aiml, filename)
            except ParserException as parser_excep:
                parser_excep.filename = filename
                raise parser_excep
            except ET.ParseError as xmlpe:
                xmlpe.filename = filename
                xmlpe.xml_exception = xmlpe

    def parse_from_text(self, text):
        """
         Parse an AIML text version of an aiml file and return all the cateogeries found in the file
         :param text: Fully validated AIML snippet
         :return list of categories parsed from file:
         """

        aiml = ET.fromstring(text)

        if aiml is None or aiml.tag != 'aiml':
            ParserException("Error, root tag is not <aiml>", filename="text")
        else:
            self.parse_aiml(aiml, "text")

    #########################################################################################
    #
    #   <?xml version = "1.0" encoding = "UTF-8"?>
    #   <aiml>
    #       <category>
    #           :
    #       </category>
    #       <topic>
    #           <category>
    #           :
    #           </category>
    #       </topic>
    #   </aiml>
    #

    def parse_aiml(self, aiml_xml, filename):
        self.parse_version(aiml_xml)

        categories_found = False
        for expression in aiml_xml:
            if expression.tag == 'topic':
                try:
                    self.parse_topic(expression)
                    categories_found = True
                except ParserException as parser_excep:
                    parser_excep.filename = filename
                    logging.error(parser_excep.format_message())
                    if self.stop_on_invalid is True:
                        raise parser_excep

            elif expression.tag == 'category':
                try:
                    self.parse_category(expression)
                    categories_found = True
                except ParserException as parser_excep:
                    parser_excep.filename = filename
                    logging.error(parser_excep.format_message())
                    if self.stop_on_invalid is True:
                        raise parser_excep

            else:
                raise ParserException("Error, unknown top level tag, %s" %
                                      expression.tag,
                                      xml_element=expression)

        if categories_found is False:
            logging.warning("no categories in aiml file")
            if self.stop_on_invalid is True:
                raise ParserException("Error, no categories in aiml file",
                                      filename=filename)

    #########################################################################################
    #
    # AIML_VERSION ::== 0.9 | 1.0 | 1.1 | 2.0
    #

    def parse_version(self, aiml):
        if 'version' in aiml.attrib:
            self._version = aiml.attrib['version']
            if self._version not in ['0.9', '1.0', '1.1', '2.0']:
                if self._supress_warnings is False:
                    logging.warning(
                        "Version number not a supported version: %s",
                        self._version)
        else:
            if self._supress_warnings is False:
                logging.warning("No version info, defaulting to 2.0")
            self._version = "2.0"

    #########################################################################################
    #
    # TOPIC_EXPRESSION:: == <topic name = "PATTERN_EXPRESSION" > (CATEGORY_EXPRESSION) + < / topic >
    #
    # PATTERN_EXPRESSION:: == WORD | PRIORITY_WORD | WILDCARD | SET_STATEMENT | PATTERN_SIDE_BOT_PROPERTY_EXPRESSION
    # PATTERN_EXPRESSION:: == PATTERN_EXPRESSION PATTERN_EXPRESSION
    #
    # This means both topic and that can also be a set of words, stars, hash, sets and bots
    #
    # CATEGORY_EXPRESSION:: == <category>
    #                               <pattern> PATTERN_EXPRESSION </pattern>
    #                              (<that> PATTERN_EXPRESSION </that>)
    #                              (<topic> PATTERN_EXPRESSION </topic>)
    #                              < template > TEMPLATE_EXPRESSION < / template >
    #                          </category>

    def parse_topic(self, topic_element):

        if 'name' in topic_element.attrib:
            name = topic_element.attrib['name']
            if name is None or len(name) == 0:
                raise ParserException("Topic name empty or null",
                                      xml_element=topic_element)
            xml = "<topic>%s</topic>" % name
            logging.info("Topic attrib converted to %s", xml)
            topic_pattern = ET.fromstring(xml)
        else:
            raise ParserException("Error, missing name attribute for topic",
                                  xml_element=topic_element)

        category_found = False
        for child in topic_element:
            logging.debug(child.tag)
            if child.tag == 'category':
                self.parse_category(child, topic_pattern)
                category_found = True
            else:
                raise ParserException("Error unknown child node of topic, %s" %
                                      child.tag,
                                      xml_element=topic_element)

        if category_found is False:
            raise ParserException("Error, no categories in topic",
                                  xml_element=topic_element)

    def parse_category(self,
                       category_xml,
                       topic_element=None,
                       add_to_graph=True):

        topics = category_xml.findall('topic')
        if topic_element is not None:
            if len(topics) > 0:
                raise ParserException(
                    "Error, topic exists in category AND as parent node",
                    xml_element=category_xml)

        else:
            if len(topics) > 1:
                raise ParserException(
                    "Error, multiple <topic> nodes found in category",
                    xml_element=category_xml)
            elif len(topics) == 1:
                topic_element = topics[0]
            else:
                topic_element = ET.fromstring("<topic>*</topic>")

        thats = category_xml.findall('that')
        if len(thats) > 1:
            raise ParserException(
                "Error, multiple <that> nodes found in category",
                xml_element=category_xml)
        elif len(thats) == 1:
            that_element = thats[0]
        else:
            that_element = ET.fromstring("<that>*</that>")

        templates = category_xml.findall('template')
        if len(templates) == 0:
            raise ParserException("Error, no template node found in category",
                                  xml_element=category_xml)
        elif len(templates) > 1:
            raise ParserException(
                "Error, multiple <template> nodes found in category",
                xml_element=category_xml)
        else:
            template_graph_root = self.template_parser.parse_template_expression(
                templates[0])

        patterns = category_xml.findall('pattern')
        if len(patterns) == 0:
            raise ParserException("Error, no pattern node found in category",
                                  xml_element=category_xml)
        elif len(patterns) > 1:
            raise ParserException(
                "Error, multiple <pattern> nodes found in category",
                xml_element=category_xml)
        else:
            if add_to_graph is True:
                self.pattern_parser.add_pattern_to_graph(
                    patterns[0], topic_element, that_element,
                    template_graph_root)
                self._num_categories += 1

        return (patterns[0], topic_element, that_element, template_graph_root)

    def match_sentence(self, bot, clientid, pattern_sentence, topic_pattern,
                       that_pattern):

        topic_sentence = Sentence(topic_pattern)
        that_sentence = Sentence(that_pattern)

        logging.debug(
            "AIML Parser matching sentence [%s], topic=[%s], that=[%s] ",
            pattern_sentence.text(), topic_pattern, that_pattern)

        sentence = Sentence()
        sentence.append_sentence(pattern_sentence)
        sentence.append_word('__TOPIC__')
        sentence.append_sentence(topic_sentence)
        sentence.append_word('__THAT__')
        sentence.append_sentence(that_sentence)
        logging.debug("Matching [%s]" % sentence.words_from_current_pos(0))

        context = MatchContext()

        template = self.pattern_parser._root_node.match(
            bot, clientid, context, sentence)

        if template is not None:
            context._template_node = template

            context.list_matches()

            # Save the matched context for the associated sentence
            pattern_sentence.matched_context = context

            return context

        return None
示例#15
0
class TemplateGraphSetTests(unittest.TestCase):

    def setUp(self):
        self.parser = TemplateGraph()
        self.assertIsNotNone(self.parser)

        self.test_brain = None
        self.test_sentence = Sentence("test sentence")
        self.test_sentence._stars = ['one', 'two', 'three', 'four', 'five', 'six']
        self.test_sentence._thatstars = ["*"]
        self.test_sentence._topicstars = ["*"]

        test_config = ClientConfiguration()

        self.test_bot = Bot(Brain(BrainConfiguration()), config=test_config.bot_configuration)
        self.test_clientid = "testid"

        conversation = self.test_bot.get_conversation(self.test_clientid)
        question = Question.create_from_sentence(self.test_sentence)
        conversation._questions.append(question)

    def test_set_template_predicate_as_attrib(self):
        template = ET.fromstring("""
			<template>
				<set name="somepred">Value1</set>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)
        self.assertEqual(len(ast.children), 1)

        set_node = ast.children[0]
        self.assertIsNotNone(set_node)
        self.assertIsInstance(set_node, TemplateSetNode)
        self.assertIsNotNone(set_node.name)
        self.assertIsInstance(set_node.name, TemplateNode)
        self.assertEqual(set_node.name.resolve(None, None), "somepred")
        self.assertFalse(set_node.local)

        self.assertEqual(len(set_node.children), 1)
        self.assertEqual(set_node.children[0].resolve(None, None), "Value1")

    def test_set_template_multi_word_predicate_as_attrib(self):
        template = ET.fromstring("""
            <template>
                <set name="somepred other">Value1</set>
            </template>
            """)
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)
        self.assertEqual(len(ast.children), 1)

        set_node = ast.children[0]
        self.assertIsNotNone(set_node)
        self.assertIsInstance(set_node, TemplateSetNode)
        self.assertIsNotNone(set_node.name)
        self.assertIsInstance(set_node.name, TemplateNode)
        self.assertEqual(set_node.name.resolve(None, None), "somepred other")
        self.assertFalse(set_node.local)

        self.assertEqual(len(set_node.children), 1)
        self.assertEqual(set_node.children[0].resolve(None, None), "Value1")

    def test_set_template_predicate_nested(self):
        template = ET.fromstring("""
			<template>
				Some text here
				<set name="somepred">Value1</set>
				Some text there
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)
        self.assertEqual(len(ast.children), 7)

        set_node = ast.children[3]
        self.assertIsNotNone(set_node)
        self.assertIsInstance(set_node, TemplateSetNode)
        self.assertIsNotNone(set_node.name)
        self.assertIsInstance(set_node.name, TemplateNode)
        self.assertEqual(set_node.name.resolve(None, None), "somepred")
        self.assertFalse(set_node.local)

        self.assertEqual(len(set_node.children), 1)
        self.assertEqual(set_node.children[0].resolve(None, None), "Value1")

    def test_set_template_local_as_attrib(self):
        template = ET.fromstring("""
			<template>
				<set var="somevar">Value2</set>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)
        self.assertEqual(len(ast.children), 1)

        set_node = ast.children[0]
        self.assertIsNotNone(set_node)
        self.assertIsInstance(set_node, TemplateSetNode)
        self.assertIsNotNone(set_node.name)
        self.assertIsInstance(set_node.name, TemplateNode)
        self.assertEqual(set_node.name.resolve(None, None), "somevar")
        self.assertTrue(set_node.local)

        self.assertEqual(len(set_node.children), 1)
        self.assertEqual(set_node.children[0].resolve(None, None), "Value2")

    def test_set_template_predicate_as_child(self):
        template = ET.fromstring("""
			<template>
				<set><name>somepred</name>Value3</set>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)
        self.assertEqual(len(ast.children), 1)

        set_node = ast.children[0]
        self.assertIsNotNone(set_node)
        self.assertIsInstance(set_node, TemplateSetNode)
        self.assertIsNotNone(set_node.name)
        self.assertIsInstance(set_node.name, TemplateNode)
        self.assertEqual(set_node.name.resolve(None, None), "somepred")
        self.assertFalse(set_node.local)

        self.assertEqual(len(set_node.children), 1)
        self.assertEqual(set_node.children[0].resolve(None, None), "Value3")

    def test_set_template_local_as_child(self):
        template = ET.fromstring("""
			<template>
				<set><var>somepred</var>Value4</set>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)
        self.assertEqual(len(ast.children), 1)

        set_node = ast.children[0]
        self.assertIsNotNone(set_node)
        self.assertIsInstance(set_node, TemplateSetNode)
        self.assertIsNotNone(set_node.name)
        self.assertIsInstance(set_node.name, TemplateNode)
        self.assertEqual(set_node.name.resolve(None, None), "somepred")
        self.assertTrue(set_node.local)

        self.assertEqual(len(set_node.children), 1)
        self.assertEqual(set_node.children[0].resolve(None, None), "Value4")
示例#16
0
class AIMLParser(object):
    def __init__(self, supress_warnings=False, stop_on_invalid=False):
        self._supress_warnings = supress_warnings
        self.stop_on_invalid = stop_on_invalid
        self.pattern_parser = PatternGraph()
        self.template_parser = TemplateGraph(self)
        self._filename = "Unknown"
        self._version = "Unknown"
        self._aiml_loader = AIMLLoader(self)
        self._num_categories = 0

    @property
    def supress_warnings(self):
        return self._supress_warnings

    @property
    def num_categories(self):
        return self._num_categories

    def load_aiml(self, brain_configuration: BrainConfiguration):
        self._supress_warnings = brain_configuration.supress_warnings
        if brain_configuration.aiml_files is not None:
            aimls_loaded = self._aiml_loader.load_dir_contents(brain_configuration.aiml_files.files,
                                                               brain_configuration.aiml_files.directories,
                                                               brain_configuration.aiml_files.extension)
            logging.info("Loaded a total of %d aiml files", len(aimls_loaded))
        else:
            logging.info("No AIML files defined in configuration to load")

    def parse_from_file(self, filename):
        """
        Parse an AIML file and return all the cateogeries found in the file
        :param filename: Name of file to parse
        :return list of categories parsed from file:
        """
        self._filename = filename

        logging.info("Loading aiml file file: " + self._filename)

        try:
            tree = ET.parse(filename, parser=LineNumberingParser())
            aiml = tree.getroot()
            if aiml is None or aiml.tag != 'aiml':
                raise ParserException("Error, root tag is not <aiml>", filename=filename)
            else:
                self.parse_aiml(aiml, filename)
        except Exception as e:
            logging.error("Failed to load contents of AIML file from [%s] - [%s]"%(filename, e))


    def parse_from_text(self, text):
        """
         Parse an AIML text version of an aiml file and return all the cateogeries found in the file
         :param text: Fully validated AIML snippet
         :return list of categories parsed from file:
         """

        aiml = ET.fromstring(text)

        if aiml is None or aiml.tag != 'aiml':
            raise ParserException("Error, root tag is not <aiml>", filename="text")
        else:
            self.parse_aiml(aiml, "text")

    #########################################################################################
    #
    #   <?xml version = "1.0" encoding = "UTF-8"?>
    #   <aiml>
    #       <category>
    #           :
    #       </category>
    #       <topic>
    #           <category>
    #           :
    #           </category>
    #       </topic>
    #   </aiml>
    #

    def parse_aiml(self, aiml_xml, filename):
        self.parse_version(aiml_xml)

        categories_found = False
        for expression in aiml_xml:
            if expression.tag == 'topic':
                try:
                    self.parse_topic(expression)
                    categories_found = True
                except ParserException as parser_excep:
                    parser_excep.filename = filename
                    logging.error(parser_excep.format_message())
                    if self.stop_on_invalid is True:
                        raise parser_excep

            elif expression.tag == 'category':
                try:
                    self.parse_category(expression)
                    categories_found = True
                except ParserException as parser_excep:
                    parser_excep.filename = filename
                    logging.error(parser_excep.format_message())
                    if self.stop_on_invalid is True:
                        raise parser_excep

            else:
                raise ParserException("Error, unknown top level tag, %s" % expression.tag, xml_element=expression)

        if categories_found is False:
            logging.warning("no categories in aiml file")
            if self.stop_on_invalid is True:
                raise ParserException("Error, no categories in aiml file", filename=filename)

    #########################################################################################
    #
    # AIML_VERSION ::== 0.9 | 1.0 | 1.1 | 2.0
    #

    def parse_version(self, aiml):
        if 'version' in aiml.attrib:
            self._version = aiml.attrib['version']
            if self._version not in ['0.9', '1.0', '1.1', '2.0']:
                if self._supress_warnings is False:
                    logging.warning("Version number not a supported version: %s", self._version)
        else:
            if self._supress_warnings is False:
                logging.warning("No version info, defaulting to 2.0")
            self._version = "2.0"

    #########################################################################################
    #
    # TOPIC_EXPRESSION:: == <topic name = "PATTERN_EXPRESSION" > (CATEGORY_EXPRESSION) + < / topic >
    #
    # PATTERN_EXPRESSION:: == WORD | PRIORITY_WORD | WILDCARD | SET_STATEMENT | PATTERN_SIDE_BOT_PROPERTY_EXPRESSION
    # PATTERN_EXPRESSION:: == PATTERN_EXPRESSION PATTERN_EXPRESSION
    #
    # This means both topic and that can also be a set of words, stars, hash, sets and bots
    #
    # CATEGORY_EXPRESSION:: == <category>
    #                               <pattern> PATTERN_EXPRESSION </pattern>
    #                              (<that> PATTERN_EXPRESSION </that>)
    #                              (<topic> PATTERN_EXPRESSION </topic>)
    #                              < template > TEMPLATE_EXPRESSION < / template >
    #                          </category>

    def parse_topic(self, topic_element):

        if 'name' in topic_element.attrib:
            name = topic_element.attrib['name']
            if name is None or len(name) == 0:
                raise ParserException("Topic name empty or null", xml_element=topic_element)
            xml = "<topic>%s</topic>" % name
            logging.info("Topic attrib converted to %s", xml)
            topic_pattern = ET.fromstring(xml)
        else:
            raise ParserException("Error, missing name attribute for topic", xml_element=topic_element)

        category_found = False
        for child in topic_element:
            logging.debug(child.tag)
            if child.tag == 'category':
                self.parse_category(child, topic_pattern)
                category_found = True
            else:
                raise ParserException("Error unknown child node of topic, %s" % child.tag, xml_element=topic_element)

        if category_found is False:
            raise ParserException("Error, no categories in topic", xml_element=topic_element)

    def parse_category(self, category_xml, topic_element=None, add_to_graph=True):

        topics = category_xml.findall('topic')
        if topic_element is not None:
            if len(topics) > 0:
                raise ParserException("Error, topic exists in category AND as parent node", xml_element=category_xml)

        else:
            if len(topics) > 1:
                raise ParserException("Error, multiple <topic> nodes found in category", xml_element=category_xml)
            elif len(topics) == 1:
                topic_element = topics[0]
            else:
                topic_element = ET.fromstring("<topic>*</topic>")

        thats = category_xml.findall('that')
        if len(thats) > 1:
            raise ParserException("Error, multiple <that> nodes found in category", xml_element=category_xml)
        elif len(thats) == 1:
            that_element = thats[0]
        else:
            that_element = ET.fromstring("<that>*</that>")

        templates = category_xml.findall('template')
        if len(templates) == 0:
            raise ParserException("Error, no template node found in category", xml_element=category_xml)
        elif len(templates) > 1:
            raise ParserException("Error, multiple <template> nodes found in category", xml_element=category_xml)
        else:
            template_graph_root = self.template_parser.parse_template_expression(templates[0])

        patterns = category_xml.findall('pattern')
        if len(patterns) == 0:
            raise ParserException("Error, no pattern node found in category", xml_element=category_xml)
        elif len(patterns) > 1:
            raise ParserException("Error, multiple <pattern> nodes found in category", xml_element=category_xml)
        else:
            if add_to_graph is True:
                self.pattern_parser.add_pattern_to_graph(patterns[0], topic_element, that_element, template_graph_root)
                self._num_categories += 1

        return (patterns[0], topic_element, that_element, template_graph_root)

    def match_sentence(self, bot, clientid, pattern_sentence, topic_pattern, that_pattern):

        topic_sentence = Sentence(topic_pattern)
        that_sentence = Sentence(that_pattern)

        logging.debug("AIML Parser matching sentence [%s], topic=[%s], that=[%s] ", pattern_sentence.text(), topic_pattern, that_pattern)

        sentence = Sentence()
        sentence.append_sentence(pattern_sentence)
        sentence.append_word('__TOPIC__')
        sentence.append_sentence(topic_sentence)
        sentence.append_word('__THAT__')
        sentence.append_sentence(that_sentence)
        logging.debug("Matching [%s]"%sentence.words_from_current_pos(0))

        context = MatchContext()

        template = self.pattern_parser._root_node.match(bot, clientid, context, sentence)

        if template is not None:
            context._template_node = template

            context.list_matches()

            # Save the matched context for the associated sentence
            pattern_sentence.matched_context = context

            return context

        return None
示例#17
0
class TemplateGraphDateTimeTests(unittest.TestCase):

    def setUp(self):
        self.parser = TemplateGraph()
        self.assertIsNotNone(self.parser)

        self.test_brain = None
        self.test_sentence = Sentence("test sentence")
        self.test_sentence._stars = ['one', 'two', 'three', 'four', 'five', 'six']
        self.test_sentence._thatstars = ["*"]
        self.test_sentence._topicstars = ["*"]

        test_config = ClientConfiguration()

        self.test_bot = Bot(Brain(BrainConfiguration()), config=test_config.bot_configuration)
        self.test_clientid = "testid"

        conversation = self.test_bot.get_conversation(self.test_clientid)
        question = Question.create_from_sentence(self.test_sentence)
        conversation._questions.append(question)

    def test_date_format_as_attrib(self):
        template = ET.fromstring("""
            <template>
                <date format="%c" />
            </template>
            """)
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsNotNone(ast.resolve(self.test_bot, self.test_clientid))

    def test_date_format_as_attrib_full(self):
        template = ET.fromstring("""
            <template>
                <date format="%c"></date>
            </template>
            """)
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsNotNone(ast.resolve(self.test_bot, self.test_clientid))

    def test_date_format_as_attrib_default(self):
        template = ET.fromstring("""
            <template>
                <date/>
            </template>
            """)
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsNotNone(ast.resolve(self.test_bot, self.test_clientid))

    def test_interval_values_as_attribs(self):
        template = ET.fromstring("""
            <template>
                <interval>
                    <format>%c</format>
                    <style>days</style>
                    <from>Wed Oct  5 16:35:11 2016</from>
                    <to>Fri Oct  7 16:35:11 2016</to>
                </interval>
            </template>
            """)
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertEqual(ast.resolve(self.test_bot, self.test_clientid), "2")
示例#18
0
class TemplateGraphBotTests(unittest.TestCase):

    def setUp(self):
        self.parser = TemplateGraph()
        self.assertIsNotNone(self.parser)

        self.test_brain = None
        self.test_sentence = Sentence("test sentence")
        self.test_sentence._stars = ['one', 'two', 'three', 'four', 'five', 'six']
        self.test_sentence._thatstars = ["*"]
        self.test_sentence._topicstars = ["*"]

        test_config = ClientConfiguration()

        self.test_bot = Bot(Brain(BrainConfiguration()), config=test_config.bot_configuration)
        self.test_clientid = "testid"

        conversation = self.test_bot.get_conversation(self.test_clientid)
        question = Question.create_from_sentence(self.test_sentence)
        conversation._questions.append(question)

    def test_extension_as_attrib(self):
        template = ET.fromstring("""
			<template>
				<extension path="test.parser.template.graph.test_extension.TestExtension">
				1 2 3
				</extension>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)
        self.assertEqual(len(ast.children), 1)

        ext_node = ast.children[0]
        self.assertIsNotNone(ext_node)
        self.assertIsInstance(ext_node, TemplateExtensionNode)
        self.assertIsNotNone(ext_node._path)

        self.assertEqual(len(ext_node.children), 3)
        self.assertEqual("executed", ext_node.resolve(None, None))

    def test_extension_as_child(self):
        template = ET.fromstring("""
            <template>
                <extension>
                    <path>test.parser.template.graph.test_extension.TestExtension</path>
                    1 2 3
                </extension>
            </template>
            """)
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)
        self.assertEqual(len(ast.children), 1)

        ext_node = ast.children[0]
        self.assertIsNotNone(ext_node)
        self.assertIsInstance(ext_node, TemplateExtensionNode)
        self.assertIsNotNone(ext_node._path)

        self.assertEqual(len(ext_node.children), 3)
        self.assertEqual("executed", ext_node.resolve(None, None))
示例#19
0
class TemplateGraphSraiTests(unittest.TestCase):
    def setUp(self):
        self.parser = TemplateGraph()
        self.assertIsNotNone(self.parser)

        self.test_brain = None
        self.test_sentence = Sentence("test sentence")
        self.test_sentence._stars = [
            'one', 'two', 'three', 'four', 'five', 'six'
        ]
        self.test_sentence._thatstars = ["*"]
        self.test_sentence._topicstars = ["*"]

        test_config = ClientConfiguration()

        self.test_bot = Bot(Brain(BrainConfiguration()),
                            config=test_config.bot_configuration)
        self.test_clientid = "testid"

        conversation = self.test_bot.get_conversation(self.test_clientid)
        question = Question.create_from_sentence(self.test_sentence)
        conversation._questions.append(question)

    def test_srai_template_simple(self):
        template = ET.fromstring("""
            <template>
                <srai>
                    SRAI this text
                </srai>
            </template>
            """)
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)

        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)
        self.assertIsNotNone(ast.children[0])
        self.assertIsInstance(ast.children[0], TemplateSRAINode)

        self.assertIsNotNone(ast.children[0].children)
        self.assertEqual(3, len(ast.children[0].children))
        self.assertIsInstance(ast.children[0].children[0], TemplateWordNode)
        self.assertIsInstance(ast.children[0].children[1], TemplateWordNode)
        self.assertIsInstance(ast.children[0].children[2], TemplateWordNode)

    def test_srai_template_nested(self):
        template = ET.fromstring("""
            <template>
                <srai>
                    SRAI This and <srai>SRAI that</srai>
                </srai>
            </template>
            """)
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)

        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)
        self.assertIsNotNone(ast.children[0])
        self.assertIsInstance(ast.children[0], TemplateSRAINode)

        self.assertIsNotNone(ast.children[0].children)
        self.assertEqual(4, len(ast.children[0].children))
        self.assertIsInstance(ast.children[0].children[0], TemplateWordNode)
        self.assertIsInstance(ast.children[0].children[1], TemplateWordNode)
        self.assertIsInstance(ast.children[0].children[2], TemplateWordNode)
        self.assertIsInstance(ast.children[0].children[3], TemplateSRAINode)

        self.assertIsNotNone(ast.children[0].children[3].children)
        self.assertEqual(2, len(ast.children[0].children[3].children))
        self.assertIsInstance(ast.children[0].children[3].children[0],
                              TemplateWordNode)
        self.assertIsInstance(ast.children[0].children[3].children[1],
                              TemplateWordNode)
示例#20
0
class TemplateGraphGetTests(unittest.TestCase):

    def setUp(self):
        self.parser = TemplateGraph()
        self.assertIsNotNone(self.parser)

        self.test_brain = None
        self.test_sentence = Sentence("test sentence")
        self.test_sentence._stars = ['one', 'two', 'three', 'four', 'five', 'six']
        self.test_sentence._thatstars = ["*"]
        self.test_sentence._topicstars = ["*"]

        test_config = ClientConfiguration()

        self.test_bot = Bot(Brain(BrainConfiguration()), config=test_config.bot_configuration)
        self.test_clientid = "testid"

        conversation = self.test_bot.get_conversation(self.test_clientid)
        question = Question.create_from_sentence(self.test_sentence)
        conversation._questions.append(question)

    def test_get_template_predicate_as_attrib(self):
        template = ET.fromstring("""
			<template>
				<get name="somepred" />
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)
        self.assertEqual(len(ast.children), 1)

        get_node = ast.children[0]
        self.assertIsNotNone(get_node)
        self.assertIsInstance(get_node, TemplateGetNode)
        self.assertIsNotNone(get_node.name)
        self.assertIsInstance(get_node.name, TemplateNode)
        self.assertEqual(get_node.name.resolve(None, None), "somepred")
        self.assertFalse(get_node.local)

    def test_get_template_predicate_as_attrib_mixed(self):
        template = ET.fromstring("""
			<template>
				Hello <get name="somepred" /> how are you
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)
        self.assertEqual(len(ast.children), 5)

        get_node = ast.children[1]
        self.assertIsNotNone(get_node)
        self.assertIsInstance(get_node, TemplateGetNode)
        self.assertIsNotNone(get_node.name)
        self.assertIsInstance(get_node.name, TemplateNode)
        self.assertEqual(get_node.name.resolve(None, None), "somepred")
        self.assertFalse(get_node.local)

    def test_get_template_var_as_attrib(self):
        template = ET.fromstring("""
			<template>
				<get var="somevar" />
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)
        self.assertEqual(len(ast.children), 1)

        get_node = ast.children[0]
        self.assertIsNotNone(get_node)
        self.assertIsInstance(get_node, TemplateGetNode)
        self.assertIsNotNone(get_node.name)
        self.assertIsInstance(get_node.name, TemplateNode)
        self.assertEqual(get_node.name.resolve(None, None), "somevar")
        self.assertTrue(get_node.local)

    def test_get_template_predicate_as_child(self):
        template = ET.fromstring("""
			<template>
				<get><name>somepred as text</name></get>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)
        self.assertEqual(len(ast.children), 1)

        get_node = ast.children[0]
        self.assertIsNotNone(get_node)
        self.assertIsInstance(get_node, TemplateGetNode)
        self.assertIsNotNone(get_node.name)
        self.assertIsInstance(get_node.name, TemplateNode)
        self.assertEqual(get_node.name.resolve(None, None), "somepred as text")
        self.assertFalse(get_node.local)

    def test_get_template_local_as_child(self):
        template = ET.fromstring("""
			<template>
				<get><var>somevar</var></get>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)
        self.assertEqual(len(ast.children), 1)

        get_node = ast.children[0]
        self.assertIsNotNone(get_node)
        self.assertIsInstance(get_node, TemplateGetNode)
        self.assertIsNotNone(get_node.name)
        self.assertIsInstance(get_node.name, TemplateNode)
        self.assertEqual(get_node.name.resolve(None, None), "somevar")
        self.assertTrue(get_node.local)
示例#21
0
class TemplateGraphMapTests(unittest.TestCase):
    def setUp(self):
        self.parser = TemplateGraph()
        self.assertIsNotNone(self.parser)

        self.test_brain = None
        self.test_sentence = Sentence("test sentence")
        self.test_sentence._stars = [
            'one', 'two', 'three', 'four', 'five', 'six'
        ]
        self.test_sentence._thatstars = ["*"]
        self.test_sentence._topicstars = ["*"]

        test_config = ClientConfiguration()

        self.test_bot = Bot(Brain(BrainConfiguration()),
                            config=test_config.bot_configuration)
        self.test_clientid = "testid"

        conversation = self.test_bot.get_conversation(self.test_clientid)
        question = Question.create_from_sentence(self.test_sentence)
        conversation._questions.append(question)

    def test_map_name_as_attrib(self):
        template = ET.fromstring("""
			<template>
				<map name="somemap">sometext</map>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)
        self.assertEqual(len(ast.children), 1)

        set_node = ast.children[0]
        self.assertIsNotNone(set_node)
        self.assertIsInstance(set_node, TemplateMapNode)
        self.assertIsNotNone(set_node.name)
        self.assertIsInstance(set_node.name, TemplateNode)
        self.assertEqual(set_node.name.resolve(None, None), "somemap")

        self.assertEqual(len(set_node.children), 1)
        self.assertEqual(set_node.children[0].resolve(None, None), "sometext")

    def test_map_name_as_child(self):
        template = ET.fromstring("""
			<template>
				<map><name>somemap</name>sometext</map>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)
        self.assertEqual(len(ast.children), 1)

        set_node = ast.children[0]
        self.assertIsNotNone(set_node)
        self.assertIsInstance(set_node, TemplateMapNode)
        self.assertIsNotNone(set_node.name)
        self.assertIsInstance(set_node.name, TemplateNode)
        self.assertEqual(set_node.name.resolve(None, None), "somemap")

        self.assertEqual(len(set_node.children), 1)
        self.assertEqual(set_node.children[0].resolve(None, None), "sometext")
示例#22
0
class TemplateGraphStarTests(unittest.TestCase):
    def setUp(self):
        self.parser = TemplateGraph()
        self.assertIsNotNone(self.parser)

        self.test_brain = None
        self.test_sentence = Sentence("test sentence")
        self.test_sentence._stars = [
            'one', 'two', 'three', 'four', 'five', 'six'
        ]
        self.test_sentence._thatstars = ["*"]
        self.test_sentence._topicstars = ["*"]

        test_config = ClientConfiguration()

        self.test_bot = Bot(Brain(BrainConfiguration()),
                            config=test_config.bot_configuration)
        self.test_clientid = "testid"

        conversation = self.test_bot.get_conversation(self.test_clientid)
        question = Question.create_from_sentence(self.test_sentence)
        conversation._questions.append(question)

    def test_star_no_index_full(self):
        template = ET.fromstring("""
            <template>
                <star></star>
            </template>
        """)
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsNotNone(ast.children)
        self.assertEqual(1, len(ast.children))
        self.assertIsInstance(ast.children[0], TemplateStarNode)
        self.assertEqual(ast.resolve(self.test_bot, self.test_clientid), "one")

    def test_star_no_index_full_embedded(self):
        template = ET.fromstring("""
            <template>
                Hello <star></star>
            </template>
            """)
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsNotNone(ast.children)
        self.assertEqual(2, len(ast.children))
        self.assertIsInstance(ast.children[0], TemplateWordNode)
        self.assertIsInstance(ast.children[1], TemplateStarNode)
        self.assertEqual(ast.resolve(self.test_bot, self.test_clientid),
                         "Hello one")

    def test_star_no_index_short(self):
        template = ET.fromstring("""
			<template>
				<star />
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsNotNone(ast.children)
        self.assertEqual(1, len(ast.children))
        self.assertIsInstance(ast.children[0], TemplateStarNode)
        self.assertEqual(ast.resolve(self.test_bot, self.test_clientid), "one")

    def test_star_index_as_child(self):
        template = ET.fromstring("""
			<template>
				<star><index>2</index></star>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsNotNone(ast.children)
        self.assertEqual(1, len(ast.children))
        self.assertIsInstance(ast.children[0], TemplateStarNode)
        self.assertEqual(ast.resolve(self.test_bot, self.test_clientid), "two")

    def test_star_index_as_attrib_full(self):
        template = ET.fromstring("""
			<template>
				<star index="3"></star>
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast)
        self.assertIsNotNone(ast.children)
        self.assertEqual(1, len(ast.children))
        self.assertIsInstance(ast.children[0], TemplateStarNode)
        self.assertEqual(ast.resolve(self.test_bot, self.test_clientid),
                         "three")

    def test_star_index_as_attrib_short(self):
        template = ET.fromstring("""
			<template>
				<star index="4" />
			</template>
			""")
        ast = self.parser.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsNotNone(ast.children)
        self.assertEqual(1, len(ast.children))
        self.assertIsInstance(ast.children[0], TemplateStarNode)
        self.assertEqual(ast.resolve(self.test_bot, self.test_clientid),
                         "four")