def generateAbortNode(root, parent, settings):
    global VERBOSE
    # node
    abortNode = LET.Element('node')
    generateNodeName(abortNode, 'ABORT_')
    if VERBOSE:
        eprintf('Generate abort node for parent: %s named: %s\n',
                parent.find('name').text if parent is not None else 'root',
                abortNode.find('name').text)
    # condition
    abortNodeCondition = LET.Element('condition')
    abortNodeCondition.text = DEFAULT_CONDITION_ABORT + (
        ' and intent.confidence >' +
        settings.get('confidence') if 'confidence' in settings.attrib else '')

    abortNode.append(abortNodeCondition)
    # output
    abortNodeOutput = LET.Element('output')
    if parent is not None:
        abortNodeOutput.text = settings.find('message').text if settings.find(
            'message') is not None else DEFAULT_ABORT_MESSAGE.text
    else:
        abortNodeOutput.text = settings.find(
            'message_cannot').text if settings.find(
                'message_cannot'
            ) is not None else DEFAULT_ABORT_MESSAGE_CANNOT.text
    abortNode.append(abortNodeOutput)
    # goto
    if settings.find('goto') is not None:
        abortNode.append(copy.deepcopy(settings.find('goto')))
    return abortNode
def generateAgainNode(root, parent, settings):
    global VERBOSE
    # node
    againNode = LET.Element('node')
    generateNodeName(againNode, 'AGAIN_')
    if VERBOSE:
        eprintf('Generate again node for parent: %s named: %s\n',
                parent.find('name').text if parent is not None else 'root',
                againNode.find('name').text)
    # condition
    againNodeCondition = LET.Element('condition')
    againNodeCondition.text = DEFAULT_CONDITION_AGAIN + (
        ' and intent.confidence >' +
        settings.get('confidence') if 'confidence' in settings.attrib else '')
    againNode.append(againNodeCondition)
    # output
    againNodeOutput = LET.Element('output')
    againNodeOutput.text = '$againMessage'
    againNode.append(againNodeOutput)
    # goto
    againNodeGoto = LET.Element('goto')
    againNodeGotoTarget = LET.Element('target')
    againNodeGotoTarget.text = root.find('node').find('name').text
    againNodeGoto.append(againNodeGotoTarget)
    againNode.append(againNodeGoto)
    return againNode
Exemplo n.º 3
0
def generateBackNode(root, parent, settings):
    global VERBOSE
    # node
    backNode = LET.Element('node')
    generateNodeName(backNode, 'BACK_')
    if VERBOSE: eprintf('Generate back node for parent: %s named: %s\n', parent.find('name').text if parent is not None else 'root', backNode.find('name').text)
    # condition
    backNodeCondition = LET.Element('condition')
    backNodeCondition.text = DEFAULT_CONDITION_BACK + (' and intent.confidence >' + settings.get('confidence') if 'confidence' in settings.attrib else '')
    backNode.append(backNodeCondition)
    if parent is not None and parent in parent_map and parent_map[parent] in parent_map:
        # output
        backNodeOutput = LET.Element('output')
        backNodeOutput.text = settings.find('message').text if settings.find('message') is not None else DEFAULT_BACK_MESSAGE.text
        backNode.append(backNodeOutput)
        # goto
        backNodeGoto = LET.Element('goto', {'selector':'body'})
        backNodeTarget = LET.Element('target')
        backNodeTarget.text = parent_map[parent_map[parent]].find('name').text
        backNodeGoto.append(backNodeTarget)
        backNode.append(backNodeGoto)
    else:
        # output
        backNodeOutput = LET.Element('output')
        if parent is not None:
            backNodeOutput.text = settings.find('message_to_main').text if settings.find('message_to_main') is not None else DEFAULT_BACK_MESSAGE_TO_MAIN.text
        else:
            backNodeOutput.text = settings.find('message_cannot').text if settings.find('message_cannot') is not None else DEFAULT_BACK_MESSAGE_CANNOT.text
        backNode.append(backNodeOutput)
    return backNode
Exemplo n.º 4
0
def generateRepeatNode(parent, root, output, attempts, varName, varValue, goto):
    global VERBOSE
    # node
    repeatNode = LET.Element('node')
    generateNodeName(repeatNode, 'REPEAT_')
    if VERBOSE: eprintf('Generate repeat node for parent: %s named: %s START\n', parent.find('name').text if parent is not None else 'root', repeatNode.find('name').text)
    # condition
    repeatNodeCondition = LET.Element('condition')
    repeatNodeCondition.text = ('$' + varName + ' == null or ' if attempts == 0 else '') + '$' + varName + ' >= ' + str(attempts)
    repeatNode.append(repeatNodeCondition)
    # context
    repeatNodeContext = LET.Element('context')
    repeatVariable = LET.Element(varName)
    repeatVariable.text = str(varValue)
    if isinstance(varValue, int):
        repeatVariable.set('type', 'number')
    repeatNodeContext.append(repeatVariable)
    repeatNode.append(repeatNodeContext)
    # output
    repeatNode.append(copy.deepcopy(output))
    # goto
    if goto is not None:
        repeatNode.append(copy.deepcopy(goto))
    root.append(repeatNode)
    if VERBOSE: eprintf('Generate repeat node for parent: %s named: %s END\n', parent.find('name').text if parent is not None else 'root', repeatNode.find('name').text)
Exemplo n.º 5
0
 def saveConfiguration(self, configFileName):
     outputConfig = configparser.ConfigParser()
     for optionUniqueName in self.__dict__:
         namesList = optionUniqueName.split(Cfg.sectionDelimiter)
         # find section and option names
         if len(namesList) > 1:
             section = namesList[0]
             option = Cfg.sectionDelimiter.join(namesList[1:])
         else:
             eprintf(
                 "WARNING: Missing section name in parameter name '%s', skipping.\n",
                 optionUniqueName)
             continue
         # create non existing sections
         if not outputConfig.has_section(section):
             outputConfig.add_section(section)
         # convert types to string
         if isinstance(getattr(self, optionUniqueName), list):
             outputConfig.set(section, option,
                              ','.join(getattr(self, optionUniqueName)))
         elif isinstance(getattr(self, optionUniqueName), bool):
             outputConfig.set(section, option,
                              str(getattr(self, optionUniqueName)))
         else:
             outputConfig.set(section, option,
                              getattr(self, optionUniqueName))
     try:
         with open(configFileName, 'w') as configFile:
             outputConfig.write(configFile)
     except IOError:
         eprintf('ERROR: Cannot save config file %s\n', configFileName)
Exemplo n.º 6
0
def validate(xml):
    global schema, VERBOSE
    try:
        schema.assertValid(xml)
        if VERBOSE: eprintf("XML is valid\n")
    except LET.XMLSchemaError:
        eprintf("Invalid XML %s!\n")
Exemplo n.º 7
0
def validateNodeName(node):
    global names
    name = node.find('name').text
    # check characters (Node names can only contain letters, numbers, hyphens and underscores)
    pattern = re.compile("[\w-]+", re.UNICODE)
    if not pattern.match(name):
        eprintf("Illegal name of the node: '%s'\nNode names can only contain letters, numbers, hyphens and underscores.\n", name)
        exit(1)
Exemplo n.º 8
0
def isFalse(autogenerate, attributeName):
        attributeValue = autogenerate.get(attributeName)
        if attributeValue == None or attributeValue == 'true':
            return False;
        elif attributeValue == 'false':
            return True
        else:
            eprintf('Unknown value of \'%s\' tag: %s.\n', attributeName, attributeValue)
            return False
    def parseXLSXIntoDataBlocks(self, filename):
        """ Read Excel spreadsheet in T2C format. Store the data as tuples (domain, prefix, intent, rawBlock) into private field. """

        printf('Processing xlsx file: %s\n', filename)
        if not os.path.exists(filename):
            eprintf('Error: File does not exist: %s\n', filename)
            return {}

        try:
            domainName = unicode(
                toIntentName(NAME_POLICY, None,
                             os.path.splitext(os.path.split(filename)[1])[0]),
                'utf-8')
            workbook = load_workbook(filename=filename, read_only=True)
        except (IOError, BadZipfile):
            eprintf(
                'Error: File does not seem to be a valid Excel spreadsheet: %s\n',
                filename)
            return {}

        # Process all the tabs of the file
        for sheet in workbook.worksheets:
            printf(' Sheet: %s\n', sheet.title)
            prefix = unicode(sheet.title, 'utf-8')
            currentBlock = []

            # Separate all data blocks in the sheet, if the currentBlock starts with header, it is considered to be part of currentBlock
            for row in sheet.iter_rows(max_col=4):
                validRow = False
                # Check if the row is valid. Row is valid if it contains at least one column not empty and different from comment
                for columnIndex in range(0, 4):
                    if row[columnIndex] and row[columnIndex].value and not (
                            row[columnIndex].value.startswith('//')):
                        validRow = True
                # Three slashes in the first cell cause whole rest of the line to be treated as comment
                if row[0].value and row[0].value.startswith('///'):
                    validRow = False

                # If empty line or header, we store the previous currentBlock-if any
                if not validRow:
                    if currentBlock:
                        self.__createBlock(domainName, prefix, currentBlock)
                    currentBlock = []
                else:
                    # if valid row - we add it to block
                    currentBlock.append(
                        (row[0].value.strip() if row[0].value
                         and not row[0].value.startswith('//') else None,
                         row[1].value.strip() if row[1].value
                         and not row[1].value.startswith('//') else None,
                         row[2].value.strip() if row[2].value
                         and not row[2].value.startswith('//') else None,
                         row[3].value.strip() if row[3].value
                         and not row[3].value.startswith('//') else None))
            if currentBlock:
                self.__createBlock(domainName, prefix, currentBlock)
Exemplo n.º 10
0
def importText(importTree, config):
    imports = importTree.xpath('//importText')
    for imp in imports:
        if VERBOSE: eprintf('Importing %s\n', os.path.join(os.path.dirname(getattr(config, 'common_dialog_main')),*filename))
        filename = imp.text.split('/') 
        fp = io.open(os.path.join(os.path.dirname(getattr(config, 'common_dialog_main')),*filename) ,'r', encoding='utf-8')
        importTxt = fp.read()
        fp.close()
        imp.getparent().text = ("" if imp.getparent().text is None else imp.getparent().text) + importTxt + ("" if imp.tail is None else imp.tail)
        imp.getparent().remove(imp)
Exemplo n.º 11
0
def findAllNodeNames(tree):
    names = []
    nodesWithNames = tree.xpath('//node[@name]')
    for nodeWithName in nodesWithNames:
        if nodeWithName.get('name') in names:
            eprintf('ERROR: Duplicit node name found: %s\n', nodeWithName.get('name'))
            exit(1)
        else:
            names.append(nodeWithName.get('name'))
    return names
Exemplo n.º 12
0
def importNodes(root, config):
    global rootGlobal, VERBOSE, names
    # IMPORT AND APPEND NODES
    defaultNode = None
    if len(root) > 0 and (root[len(root)-1].find('condition') is None or (root[len(root)-1].find('condition') is not None and root[len(root)-1].find('condition').text == 'anything_else')):
        # IF LAST NODE DOES NOT HAVE CONDITION OR HAS CONDITION SET TO 'anything_else'
        defaultNode = root[len(root)-1]

    for node in root.findall('import'):
        if VERBOSE: eprintf('Importing %s\n', os.path.join(os.path.dirname(getattr(config, 'common_dialog_main')),node.text))
        importPath = node.text.split('/')
        importTree = LET.parse(os.path.join(os.path.dirname(getattr(config, 'common_dialog_main')),*importPath))
        importText(importTree, config)
        replace_config_variables(importTree)
        
        if schema is not None:
            validate(importTree)

        importRoot = importTree.getroot()
        for importChild in importRoot.findall('node'):
            #eprintf('  Importing node: %s\n', importChild)
            nodeWithTheSameCondition = getNodeWithTheSameCondition(root, importChild)
            """
            if nodeWithTheSameCondition is not None:
                # SKIP NODES WITH SAME CONDITIONS
                #eprintf('    Skipping node (same condition): %s\n', nodeWithTheSameCondition)
                if importChild.find('context') is not None:
                    #eprintf('      Context found for node: %s\n', importChild)
                    if nodeWithTheSameCondition.find('context') is None:
                        #eprintf('      Creating context for node: %s\n', nodeWithTheSameCondition)
                        nodeWithTheSameConditionContext = LET.Element('context')
                        nodeWithTheSameCondition.append(nodeWithTheSameConditionContext)
                    # COPY ALL CONTEXT TO NODE WITH SAME CONDITION
                    for context in importChild.find('context'):
                        #eprintf('      Appending context: %s\n', context)
                        nodeWithTheSameCondition.find('context').append(context)
            else:
                # INSERT NODE

                #eprintf('    Appending node: %s\n', importChild) 
            """
            root.append(importChild)

    if defaultNode is not None:
        # MOVE DEFAULT_NODE TO THE END
        root.remove(defaultNode)
        root.append(defaultNode)

    # PROCESS CHILD NODES
    for node in root.findall('node'):
        children = node.find('nodes')
        if children is not None:
            importNodes(children, config)
Exemplo n.º 13
0
    def _createOutputElement(self, channels, buttons):
        """ Convert output channels into XML structure. """
        outputXml = XML.Element('output')
        if channels:
            for channelName, channelValues in channels.iteritems():
                if channelName == '1':
                    textValuesXml = XML.Element('textValues')

                    for item in channelValues:
                        textValuesXml.append(
                            self._createXmlElement('values', item))
                        outputXml.append(textValuesXml)
                    continue

                output = self._concatenateOutputs(channelValues)
                if channelName == '2':
                    outputXml.append(self._createXmlElement('timeout', output))

                elif channelName == '3':
                    outputXml.append(self._createXmlElement('sound', output))

                elif channelName == '4':
                    outputXml.append(self._createXmlElement('tts', output))

                elif channelName == '5':
                    outputXml.append(
                        self._createXmlElement('talking_head', output))

                elif channelName == '6':
                    outputXml.append(
                        self._createXmlElement('paper_head', output))

                elif channelName == '7':
                    outputXml.append(self._createXmlElement(
                        'graphics', output))

                elif channelName == '8':
                    outputXml.append(self._createXmlElement('url', output))

                else:
                    eprintf('Warning: Unrecognized channel: %s, value: %s\n',
                            channelName, output)

        if buttons:
            genericXml = XML.Element('generic', structure='listItem')
            for buttonLabel, buttonValue in buttons.iteritems():
                optionsXml = XML.Element('options')
                optionsXml.append(self._createXmlElement('label', buttonLabel))
                optionsXml.append(self._createXmlElement('value', buttonValue))
                genericXml.append(optionsXml)
            outputXml.append(genericXml)

        return outputXml
Exemplo n.º 14
0
    def __handleIntentBlock(self, intent, block, domain):
        """ Read intent definition from current block and save it into Dialog data structure. """

        # blockLength = len(block)
        startsWithHash = block[0][0].startswith(u'#')

        if not startsWithHash and not block[0][1]:
            eprintf('Warning: Wrong intent definition format for line starting with: %s\n', intent)
            return

        intentData = self._dialogData.getIntentData(intent, domain)

        for row in block:
            if row[0] and not row[0].startswith(u'#'):
                intentData.addIntentAlternative(row[0])  # Collect intent definition
            if row[1]:
                intentData.addRawOutput(row[1:], self._labelsMap)  # Collect text output
Exemplo n.º 15
0
    def __handleJumpToDefinition(self, jumpto, labelsMap):
        selector = 'user_input'
        label = jumpto
        if len(jumpto) > 2 and jumpto[1] == '_':
            label = jumpto[2:]
            if jumpto[0] == 'b':
                selector = 'body'
            elif jumpto[0] == 'c':
                selector = 'condition'

        if label not in labelsMap:
            self.setJumpTo(
                label,
                selector)  # label can point at a node name defined externally
            eprintf(
                'Warning: using jumpto label that was not defined before: %s, expecting that it is external reference to a node name.\n',
                label)
        else:
            self.setJumpTo(labelsMap[label], selector)
Exemplo n.º 16
0
    def addRawOutput(self, rawOutputs, labelsMap):
        """ Read the raw output and store all data from it - 
            channel outputs, context variables and jumpto definitions. """
        self._rawOutputs.append(rawOutputs)
        if not isinstance(rawOutputs, tuple) or len(rawOutputs) < 1:
            eprintf('Warning: rawOutput does not contain any data: %s\n',
                    rawOutputs)

        for item in re.split('%%', rawOutputs[0]):
            if not item: continue
            if item.startswith(u'$'):
                self.__handleVariableDefinition(item[1:])
            elif item.startswith(u'B'):
                self.__handleButtonDefinition(item[1:])
            elif item.startswith(u':'):
                self.__handleJumpToDefinition(item[1:], labelsMap)
            else:
                self.__handleChannelDefinition(item)

        if len(rawOutputs) >= 3:
            if rawOutputs[1]:
                self.__handleButtonDefinition(rawOutputs[1])
            if rawOutputs[2]:
                self.__handleJumpToDefinition(rawOutputs[2], labelsMap)
Exemplo n.º 17
0
def mergeSettings(childSettings, parentSettings):
    if childSettings is None:
        if VERBOSE: eprintf('Returning parent settings\n')
        return parentSettings
    if parentSettings is None:
        if VERBOSE: eprintf('Returning child settings\n')
        return childSettings
    # for all child elements
    for element in parentSettings:
        if childSettings.find(element.tag) is None:
            childSettings.append(element)
    # for all attributes
    for attributeName in parentSettings.attrib:
        if childSettings.get(attributeName) is None:
            childSettings.set(attributeName, parentSettings.get(attributeName))
    if VERBOSE: eprintf('Returning merged settings\n')
    return childSettings
Exemplo n.º 18
0
    def __init__(self, args):
        logging.basicConfig(filename='log.log', level=logging.INFO)
        logging.info('cfg.__init__')
        self.config = {}

        # Sections (names can not contain '_')
        commonSection = 'common'
        conversationSection = 'conversation'
        cloudfunctionsSection = 'cloudfunctions'
        workspaceSection = 'workspace'
        weatherSection = 'weatherservice'
        replaceSection = 'replace'
        versionSection = 'version'
        contextSection = 'context'
        commonSection = 'common'

        # List of attributes of framework section to be appended rather then ovewrriden (if the same parameter is defined in more config files)
        frameworkAppend = [
            'xls', 'intents', 'entities', 'dialogs', 'functions',
            'generated_intents', 'generated_entities', 'generated_dialog'
        ]

        if args.common_configFilePaths:
            try:
                for common_configFilePath in args.common_configFilePaths:  # go over all the config files and collect all parameters
                    logging.info("Processing config file:" +
                                 common_configFilePath)
                    print("Processing config file:" + common_configFilePath)
                    configPart = configparser.ConfigParser()
                    configPart.read(common_configFilePath)
                    # Collect all attributes from all sections
                    for section in configPart.sections():
                        options = configPart.options(section)
                        for option in options:
                            optionUniqueName = self.toOptionName(
                                section, option)
                            # value can be list
                            newValueList = configPart.get(section,
                                                          option).split(',')
                            if len(newValueList) > 1:  # create list
                                newValue = newValueList
                            else:  # only single value
                                newValue = newValueList[0]
                            if hasattr(self, optionUniqueName):
                                warning = "WARNING: '" + optionUniqueName + " already exists. "
                                if (section == commonSection) and (
                                        option in frameworkAppend):  # appended
                                    logging.debug(
                                        warning + "Appending '[" +
                                        ' '.join(newValue) + "]' to [" +
                                        ' '.join(
                                            getattr(self, optionUniqueName)) +
                                        "]")
                                    setattr(self, optionUniqueName, newValue)
                                else:  # replace
                                    oldValue = getattr(self, optionUniqueName)
                                    logging.debug(warning + "Replacing '" +
                                                  oldValue + "' by '[" +
                                                  ' '.join(newValue) + "]'")
                                    setattr(self, optionUniqueName, newValue)
                            else:
                                if (section == commonSection) and (
                                        option
                                        in frameworkAppend):  # create list
                                    setattr(self, optionUniqueName, [newValue])
                                else:  # set value
                                    setattr(self, optionUniqueName, newValue)
            except IOError:
                eprintf('ERROR: Cannot load config file %s\n',
                        args.configFileName)
                sys.exit(1)

        # Set command line parameters
        # command line parameters are having precedence, therefore they are set the last
        for arg in vars(args):
            if hasattr(args, arg) and getattr(
                    args, arg):  # attribute is present and not empty
                if hasattr(self, arg):
                    eprintf(
                        "WARNING: Overwriting config file parameter '%s' with value '%s' from comman line argumets.\n",
                        arg, getattr(args, arg))
                setattr(self, arg, getattr(args, arg))
        if hasattr(self, 'common_output_config'):
            self.saveConfiguration(getattr(self, 'common_output_config'))
    parser.add_argument('-oc',
                        '--common_output_config',
                        help='output configuration file')
    parser.add_argument('-v',
                        '--common_verbose',
                        required=False,
                        help='verbosity',
                        action='store_true')
    args = parser.parse_args(sys.argv[1:])
    config = Cfg(args)
    VERBOSE = hasattr(config, 'common_verbose')

    if hasattr(config, 'common_verbose') and getattr(config, 'common_verbose'):
        name_policy = 'soft_verbose'
    if not hasattr(config, 'common_xls'):
        eprintf('ERROR: xls is not defined')
        exit(1)
    if not hasattr(config, 'common_generated_dialogs'):
        if VERBOSE:
            printf('INFO: generated_dialogs parameter is not defined\n')
    if not hasattr(config, 'common_generated_intents'):
        if VERBOSE:
            printf('INFO: generated_intents parameter is not defined\n')
    if not hasattr(config, 'common_generated_entities'):
        if VERBOSE:
            printf('INFO: generated_entities parameter is not defined\n')

    xlsxHandler = XLSXHandler()
    allDataBlocks = {
    }  # map of datablocks, key: Excel sheet name, value: list of all block in the sheet
Exemplo n.º 20
0
    # LOAD RESOURCE FILE (TRANSLATIONS)
    with open(args.resource, 'r') as resourceFile:
        translations = json.load(resourceFile)

    # REPLACE ALL CODES WITH TEXTS
    for tagToReplace in tagsToReplace:
        if tagToReplace.text is None: continue
        if VERBOSE: printf("%s: code '%s'\n", tagToReplace.tag, tagToReplace.text)
        textParts = tagToReplace.text.split()
        for textPart in textParts:
            if not textPart.startswith('%%'): continue # it is not a code
            code = toCode(NAME_POLICY, textPart[2:])
            # if this tag code is not in translations dictionary -> error
            if not code in translations:
                eprintf("ERROR: code '%s' not in resource file!\n", code)
            else:
                # replace code (introduced with double %% and followed by white character or by the end) with its translation
                newText = re.sub(r"%%"+code+"(?=\s|$)", translations[code], tagToReplace.text)
                tagToReplace.text = newText
        if VERBOSE: printf("-> translated as %s\n", tagToReplace.text)

    # OUTPUT NEW DIALOG
    if args.output is not None:
        with open (args.output, 'w') as outputFile:
            outputFile.write(LET.tostring(dialogXML, pretty_print=True, encoding='utf8'))
    elif args.inplace:
        with open (args.dialog, 'w') as outputFile:
            outputFile.write(LET.tostring(dialogXML, pretty_print=True, encoding='utf8'))
    else:
        sys.stdout.write(LET.tostring(dialogXML, pretty_print=True, encoding='utf8'))
Exemplo n.º 21
0
def printNodes(root, parent, dialogJSON):
    """Converts parsed XML to JSON structure

    Args:
        root (_Element): root of the parsed XML tree - (typically there is element "nodes" )
        parent (_Element): initially None, then parent
        dialogJSON (string): generated JSON
    """
    global firstNode, VERBOSE
    # PROCESS SIBLINGS
    previousSibling = None
    for nodeXML in root: # for each node in nodes
        if not (nodeXML.tag == 'node' or nodeXML.tag == 'slot' or nodeXML.tag == 'handler' or nodeXML.tag == 'response'):
            continue
        # fix name
        if nodeXML.find('name') is None:
            generateNodeName(nodeXML, '')
        else:
            validateNodeName(nodeXML)
        nodeJSON = {'dialog_node':nodeXML.find('name').text}
        dialogJSON.append(nodeJSON)

        children = []

        # TYPE
        if nodeXML.find('type') is not None:
            nodeJSON['type'] = nodeXML.find('type').text
        elif nodeXML.find('slots') is not None:
            nodeJSON['type'] = "frame"
        # EVENTNAME
        if nodeXML.get('eventName') is not None:
            nodeJSON['event_name'] = nodeXML.get('eventName')
            nodeJSON['type'] = 'event_handler'
        # VARIABLE
        if nodeXML.get('variable') is not None:
            nodeJSON['variable'] = nodeXML.get('variable')
            nodeJSON['type'] = 'slot'
        if nodeXML.tag == 'response':
            nodeJSON['type'] = 'response_condition'
        # CONDITION
        if nodeXML.find('condition') is not None:
            nodeJSON['conditions'] = nodeXML.find('condition').text
        elif 'type' in nodeJSON:
            if nodeJSON['type'] == 'default':
                nodeJSON['conditions'] = DEFAULT_CONDITION_ELSE
            elif nodeJSON['type'] == 'yes':
                nodeJSON['conditions'] = DEFAULT_CONDITION_YES
            elif nodeJSON['type'] == 'no':
                nodeJSON['conditions'] = DEFAULT_CONDITION_NO
            elif nodeJSON['type'] == 'slot' or nodeJSON['type'] == 'response_condition' or nodeJSON['type'] == 'event_handler':
                None
            else:
                nodeJSON['conditions'] = DEFAULT_CONDITION_ELSE
        else:
            nodeJSON['conditions'] = DEFAULT_CONDITION_ELSE
        # OUTPUT
        if nodeXML.find('output') is not None:
            outputNodeXML = nodeXML.find('output')
            for responseNodeXML in outputNodeXML.findall('response'): #responses are translated to seperate nodes
                children.append(responseNodeXML)
                outputNodeXML.remove(responseNodeXML)
            # this should be somewhere in generate
            if outputNodeXML.text: # if any free text - create an element <text> txt </text> out of it and delete it
                if outputNodeXML.text.strip():
                    outputNodeTextXML = LET.Element('text')
                    outputNodeTextXML.text = outputNodeXML.text
                    outputNodeXML.append(outputNodeTextXML)
                    # TODO save againMessage
                outputNodeXML.text = None
            if outputNodeXML.find('textValues') is not None: #rename textValues element to text
                outputNodeTextXML = outputNodeXML.find('textValues')
                outputNodeTextXML.tag = 'text'
            convertAll(nodeJSON, outputNodeXML)
        # CONTEXT
        if nodeXML.find('context') is not None:
            convertAll(nodeJSON, nodeXML.find('context')) 
        # ACTIONS
        if nodeXML.find('actions') is not None:
            actionsXML = nodeXML.find('actions')
            nodeJSON['actions'] = []
            for actionXML in actionsXML.findall('action'):
                actionJSON = {}
                convertAll(actionJSON, actionXML)
                nodeJSON['actions'].append(actionJSON['action'])
        # GO TO
        if nodeXML.find('goto') is not None:
            if nodeXML.find('goto').find('target') is None:
                eprintf('WARNING: missing goto target in node: %s\n', nodeXML.find('name').text)
            elif nodeXML.find('goto').find('target').text == '::FIRST_SIBLING':
                nodeXML.find('goto').find('target').text = next(x for x in root if x.tag == 'node').find('name').text
            gotoJson = {'dialog_node':nodeXML.find('goto').find('target').text}
            gotoJson['selector'] = nodeXML.find('goto').find('selector').text if nodeXML.find('goto').find('selector') is not None else DEFAULT_SELECTOR
            nodeJSON['go_to'] = gotoJson
        # PARENT
        if parent is not None:
            nodeJSON['parent'] = parent.find('name').text
        # PREVIOUS SIBLING
        if previousSibling is not None:
            nodeJSON['previous_sibling'] = previousSibling.find('name').text

        # CLOSE NODE
        previousSibling = nodeXML

        # ADD ALL CHILDREN NODES
        nodes = nodeXML.find('nodes')
        if nodes is not None:
            children.extend(nodes)

        # ADD ALL SLOTS (FRAME FUNCTIONALITY)
        slots = nodeXML.find('slots')
        if slots is not None:
            children.extend(slots)

        # ADD ALL HANDLERS (FRAME FUNCTIONALITY)
        handlers = nodeXML.find('handlers')
        if handlers is not None:
            children.extend(handlers)

        # PROCESS ALL CHILDREN
        if children:
            printNodes(children, nodeXML, dialogJSON)
Exemplo n.º 22
0
def generateRepeatNodes(root, parent, settings):
    global VERBOSE
    if parent is None: return
    if VERBOSE: eprintf('Generate repeat nodes for parent: %s START\n', parent.find('name').text if parent is not None else 'root')
    # ADD VARIABLE 'attempts_*' TO PARENT'S CONTEXT AND SET IT TO ZERO (FOR SURE)
    repeatVarName = 'attempts_' + parent.find('name').text.replace('-', '') # remove hyphens (they cause problems in mathematical expressions where they act as minus signs)
    # context
    context = parent.find('context')
    if context is None:
        context = LET.Element('context')
        parent.append(context)
    contextRepeat = LET.Element(repeatVarName, {'type':'number'})
    contextRepeat.text = '0'
    context.append(contextRepeat)
    # goto for repetation
    if root.find('node') is None:
      eprintf('Repeat node without options to input something!!!\n')
    repeatNodeGoto = LET.Element('goto')
    repeatNodeGotoTarget = LET.Element('target')
    repeatNodeGotoTarget.text = root.find('node').find('name').text
    repeatNodeGoto.append(repeatNodeGotoTarget)
    # max attempts
    maxAttempts = int(settings.find('attempts').text) if settings is not None and settings.find('attempts') is not None else DEFAULT_REPEAT_ATTEMPTS
    if VERBOSE: eprintf('maxAttempts: %s\n', maxAttempts)
    # output sentences
    outputs = settings.find('outputs').findall('output') if settings.find('outputs') is not None and len(settings.find('outputs').findall('output')) > 0 else DEFAULT_REPEAT_MESS_TEMPLATES['default'] 
    if VERBOSE: eprintf('nOutputs: %s\n', len(outputs))
    # LAST NODE (RETURNING TO THE MAIN MENU)
    generateRepeatNode(parent, root, outputs[-1], maxAttempts-1, repeatVarName, 0, settings.find('goto'))
    if VERBOSE: eprintf('LAST NODE\n')
    # MIDDLE NODE
    for i in range(min(maxAttempts-1, len(outputs)-1) -1, 0, -1):
        generateRepeatNode(parent, root, outputs[i], i, repeatVarName, '<?$' + repeatVarName +' + 1?>', repeatNodeGoto)
        if VERBOSE: eprintf('MIDDLE NODE number: %d\n', i)
    # FIRST (DEFAULT) NODE
    generateRepeatNode(parent, root, outputs[0], 0, repeatVarName, '<? $' + repeatVarName + ' == null ? 0 : $' + repeatVarName + ' + 1 ?>', repeatNodeGoto)
    if VERBOSE: eprintf('FIRST NODE\n')
    if VERBOSE: eprintf('Generate repeat nodes for parent: %s \n', parent.find('name').text if parent is not None else 'root')
Exemplo n.º 23
0
def generateNodes(root, parent, parentAbortSettings, parentAgainSettings, parentBackSettings, parentRepeatSettings, parentGenericSettings):
    global parent_map, VERBOSE
    # GENERATE NAMES
    for node in root.findall('node'):
        generateNodeName(node, '')
        if VERBOSE: eprintf('Found node: %s in: %s\n', node.find('name').text, parent.find('name').text if parent is not None else 'root')

    # READ NODES PROPERTIES
    abortSettings = None
    againSettings = None
    backSettings = None
    repeatSettings = None
    genericSettings = None

    for autogenerate in root.findall('autogenerate'):
        if autogenerate.get('type') == 'abort':
            if VERBOSE: eprintf('Abort settings found in parent: %s\n', parent.find('name').text if parent is not None else 'root')
            abortSettings = autogenerate
        if autogenerate.get('type') == 'again':
            if VERBOSE: eprintf('Again settings found in parent: %s\n', parent.find('name').text if parent is not None else 'root')
            againSettings = autogenerate
        if autogenerate.get('type') == 'back':
            if VERBOSE: eprintf('Back settings found in parent: %s\n', parent.find('name').text if parent is not None else 'root')
            backSettings = autogenerate
        if autogenerate.get('type') == 'repeat':
            if VERBOSE: eprintf('Repeat settings found in parent: %s\n', parent.find('name').text if parent is not None else 'root')
            repeatSettings = autogenerate
        if autogenerate.get('type') == 'generic':
            if VERBOSE: eprintf('Generic settings found in parent: %s\n', parent.find('name').text if parent is not None else 'root')
            genericSettings = autogenerate

    abortSettings = mergeSettings(abortSettings, parentAbortSettings)
    # TODO discuss how those funcitonality should work and if it is possible to implement it just in conversation
    #againSettings = mergeSettings(againSettings, parentAgainSettings)
    #backSettings = mergeSettings(backSettings, parentBackSettings)
    repeatSettings = mergeSettings(repeatSettings, parentRepeatSettings)
    genericSettings = mergeSettings(genericSettings, parentGenericSettings)

    # generate if settings exist and are not switched off
    abort = True if (abortSettings is not None and not isFalse(abortSettings, 'on')) else False
    again = True if (againSettings is not None and not isFalse(againSettings, 'on')) else False
    back = True if (backSettings is not None and not isFalse(backSettings, 'on')) else False
    repeat = True if (repeatSettings is not None and not isFalse(repeatSettings, 'on')) else False
    generic = True if (genericSettings is not None and not isFalse(genericSettings, 'on')) else False

    indexOfInsertion = len(root)
    for index in range(0, len(root)):
        node = root[index]
        if node.tag == 'node':
            condition = node.find('condition')
            # TODO check if we generate condition 'anything_else' for nodes without condition
            # we want to generate CONTROL nodes before repeat section
            if condition is None or condition.text == 'anything_else' or condition.text.startswith(('anything_else', '$tries')):
                indexOfInsertion = index
                break;

    # GENERATE NEW NODES
    if abort:
        # ABORT NODE RETURNING TO THE MAIN MENU
        root.insert(indexOfInsertion, generateAbortNode(root, parent, abortSettings))
        indexOfInsertion = indexOfInsertion + 1
    if again:
        # AGAIN NODE REPEAT CURRENT STEP
        root.insert(indexOfInsertion, generateAgainNode(root, parent, againSettings))
        indexOfInsertion = indexOfInsertion + 1
    if back:
        # BACK NODE RETURNING TO PREVIOUS NODE
        root.insert(indexOfInsertion, generateBackNode(root, parent, backSettings))
        indexOfInsertion = indexOfInsertion + 1
    if generic:
        # GENERIC NODE
        for genericChild in genericSettings:
            genericChildCopy = copy.deepcopy(genericChild)
            generateNodeName(genericChildCopy, 'GENERIC_')
            root.insert(indexOfInsertion, genericChildCopy)
            indexOfInsertion = indexOfInsertion + 1
    if repeat:
        generateRepeatNodes(root, parent, repeatSettings)

    for node in root.findall('node'):
        # PROCESS CHILD NODES
        children = node.find('nodes')
        if children is not None:
            # propagate settings only if propagation not switched off
            generateNodes(
                children,
                node,
                abortSettings if abortSettings is not None and not isFalse(abortSettings, 'propagate') else None,
                againSettings if againSettings is not None and not isFalse(againSettings, 'propagate') else None,
                backSettings if backSettings is not None and not isFalse(backSettings, 'propagate') else None,
                repeatSettings if repeatSettings is not None and not isFalse(repeatSettings, 'propagate') else None,
                genericSettings if genericSettings is not None and not isFalse(genericSettings, 'propagate') else None
            )
Exemplo n.º 24
0
    # OUTPUT NEW DIALOG
    if args.output is not None:
        with open(args.output, 'w') as outputFile:
            outputFile.write(
                LET.tostring(dialogsXML, pretty_print=True, encoding='utf8'))
    elif args.inplace:
        with open(args.dialog, 'w') as outputFile:
            outputFile.write(
                LET.tostring(dialogsXML, pretty_print=True, encoding='utf8'))
    else:
        sys.stdout.write(
            LET.tostring(dialogsXML, pretty_print=True, encoding='utf8'))

    # EXTEND RESOURCE FILE
    if args.append:
        with open(args.resource, 'r') as resourceFile:
            resourceJSON = json.load(resourceFile)
            resourceJSON.update(
                translations
            )  # add new translations to existing ones (Duplicate codes will be overwritten by new ones.)
            translations = resourceJSON

    # CREATE RESOURCE FILE
    with open(args.resource, 'w') as resourceFile:
        resourceFile.write(
            json.dumps(translations, indent=4,
                       ensure_ascii=False).encode('utf8'))

    if VERBOSE: eprintf('Texts were successfully replaced with codes.\n')
Exemplo n.º 25
0
    def _createOutputElement(self, channels, buttons):
        """ Convert output channels into XML structure. """
        outputXml = XML.Element('output')
        if channels:
            for channelName, channelValues in channels.iteritems():
                if channelName == '1':
                    textValuesXml = XML.Element('textValues')

                    for item in channelValues:
                        textValuesXml.append(
                            self._createXmlElement('values', item))
                        outputXml.append(textValuesXml)
                    continue

                output = self._concatenateOutputs(channelValues)
                if channelName == '2':
                    outputXml.append(self._createXmlElement('timeout', output))

                elif channelName == '3':
                    outputXml.append(self._createXmlElement('sound', output))

                elif channelName == '4':
                    outputXml.append(self._createXmlElement('tts', output))

                elif channelName == '5':
                    outputXml.append(
                        self._createXmlElement('talking_head', output))

                elif channelName == '6':
                    outputXml.append(
                        self._createXmlElement('paper_head', output))

                elif channelName == '7':
                    outputXml.append(self._createXmlElement(
                        'graphics', output))

                elif channelName == '8':
                    outputXml.append(self._createXmlElement('url', output))

                else:
                    eprintf('WARNING: Unrecognized channel: %s, value: %s\n',
                            channelName, output)

        if buttons:
            genericXml = XML.Element('generic', structure='listItem')
            genericXml.append(self._createXmlElement('response_type',
                                                     "option"))
            genericXml.append(self._createXmlElement('preference', "button"))
            genericXml.append(
                self._createXmlElement('title', "Fast selection buttons"))

            buttonIndex = 0
            for buttonLabel, buttonValue in buttons.iteritems():
                if buttonIndex < MAX_OPTIONS:
                    optionsXml = XML.Element('options')
                    optionsXml.append(
                        self._createXmlElement('label', buttonLabel))
                    optionsXml.append(
                        self._createXmlOption('value', buttonValue))
                    genericXml.append(optionsXml)
                else:
                    eprintf(
                        'Warning: Number of buttons is larger then %s, ignoring: %s, %s\n',
                        MAX_OPTIONS, buttonLabel, buttonLabel)
                buttonIndex += 1
            outputXml.append(genericXml)

        return outputXml
Exemplo n.º 26
0
        config = configparser.ConfigParser()
        config.read(args.config)
        workspacesUrl = config.get(conversationSection, 'url')
        version = config.get(conversationSection, 'version')
        username = config.get(conversationSection, 'username')
        printf('WCS USERNAME: %s\n', username)
        password = config.get(conversationSection, 'password')
        printf('WCS PASSWORD: %s\n', password)
        workspaceId = config.get(conversationSection,
                                 'workspace_id',
                                 fallback=None)
        if workspaceId:
            printf('WCS WORKSPACE_ID: %s\n', workspaceId)
            workspacesUrl += '/' + workspaceId
    except IOError:
        eprintf('ERROR: Cannot load config file %s\n', args.config)
        sys.exit(1)

    # wait until workspace is done with training
    checkWorkspaceTime = 0
    url = workspacesUrl + '?version=' + version
    while True:
        response = requests.get(url, auth=(username, password))
        responseJson = response.json()
        if 'error' in responseJson:
            eprintf('ERROR: %s\n', responseJson['error'])
            sys.exit(1)
        status = responseJson['status']
        printf('WCS WORKSPACE STATUS: %s\n', status)
        if status == 'Available':
            break
Exemplo n.º 27
0
            printf('-- TEST: ' + testName + '\n')
            printf('--------------------------------------------------------------------------------\n')

            # XML (new dialouge)
            dialogXml = LET.Element('testsuite')

            expectedJsonLine = expectedJsonFile.readline()
            receivedJsonLine = receivedJsonFile.readline()

            line = 0
            dialogId = 0
            # for every line
            while expectedJsonLine:
                line += 1;
                if not receivedJsonLine: # no more received line
                    eprintf('ERROR: Missing output JSON in file %s, line %d', args.receivedFileName, line)
                    sys.exit(1)
                expectedData = json.loads(expectedJsonLine)
                expectedJson = expectedData['output_message']
                receivedJson = json.loads(receivedJsonLine)

                if (dialogId == 0 or dialogId != expectedData['dialog_id']):

                    if nDialogs > 0:
                        # end previous dialog
                        printf('--------------------------------------------------------------------------------\n')
                        if nFailuresInDialog: # at least one failure in this dialog
                            printf('-- TEST RESULT: FAILED, TOTAL FAILURES: %d, LINE OF THE FIRST FAILURE: %d\n', nFailuresInDialog, firstFailedLine)
                            nDialogsFailed += 1
                        else:
                            printf('-- TEST RESULT: OK\n')
Exemplo n.º 28
0
def areSame(expectedOutputJson, receivedOutputJson, failureData, parentPath):

    printf("ARE SAME: %s and %s\n", expectedOutputJson, receivedOutputJson)

    if isinstance(expectedOutputJson, basestring):
        if not isinstance(receivedOutputJson, basestring):
            failureData['message'] = 'Received output differs in type from expected output.' + " (" + parentPath + ")"
            failureData['expectedElement'] = "Element of the type string (" + expectedOutputJson + ")"
            failureData['receivedElement'] = "Element of the type " + receivedOutputJson.__class__.__name__
            printf("Different type: %s and %s\n", expectedOutputJson, receivedOutputJson)
            return False
        if expectedOutputJson != receivedOutputJson:
            failureData['message'] = 'Received output differs from expected output.' + " (" + parentPath + ")"
            failureData['expectedElement'] = expectedOutputJson
            failureData['receivedElement'] = receivedOutputJson
            printf("NOT SAME: %s and %s\n", expectedOutputJson, receivedOutputJson)
            return False
        else:
            printf('SAME: basestring %s and %s are same\n', expectedOutputJson, receivedOutputJson)
            return True

    if isinstance(expectedOutputJson, int):
        if not isinstance(receivedOutputJson, int):
            failureData['message'] = 'Received output differs in type from expected output.' + " (" + parentPath + ")"
            failureData['expectedElement'] = "Element of the type int (" + str(expectedOutputJson) + ")"
            failureData['receivedElement'] = "Element of the type " + receivedOutputJson.__class__.__name__
            printf("Different type: %s and %s\n", expectedOutputJson, receivedOutputJson)
            return False
        if expectedOutputJson != receivedOutputJson:
            failureData['message'] = 'Received output differs from expected output.' + " (" + parentPath + ")"
            failureData['expectedElement'] = str(expectedOutputJson)
            failureData['receivedElement'] = str(receivedOutputJson)
            printf("NOT SAME: %s and %s\n", expectedOutputJson, receivedOutputJson)
            return False
        else:
            printf('SAME: int %s and %s are same\n', expectedOutputJson, receivedOutputJson)
            return True

    elif isinstance(expectedOutputJson, list):
        if not isinstance(receivedOutputJson, list):
            failureData['message'] = 'Received output differs in type from expected output.' + " (" + parentPath + ")"
            failureData['expectedElement'] = "Element of the type list"
            failureData['receivedElement'] = "Element of the type " + receivedOutputJson.__class__.__name__
            printf("Different type: %s and %s\n", expectedOutputJson, receivedOutputJson)
            return False
        if len(expectedOutputJson) != len(receivedOutputJson):
            failureData['message'] = 'List in received output differs in length from list in expected output.' + " (" + parentPath + ")"
            failureData['expectedElement'] = "List of the length " + str(len(expectedOutputJson))
            failureData['receivedElement'] = "List of the length " + str(len(receivedOutputJson))
            printf('ERROR: Different list length!\n')
            printf('expected %s\n', expectedOutputJson)
            printf('received %s\n', receivedOutputJson)
            return False
        else:
            for i in range(len(expectedOutputJson)):
                printf("STEP: Item %d\n", i)
                if not areSame(expectedOutputJson[i], receivedOutputJson[i], failureData, parentPath + " - " + str(i) + "th item in list"):
                    printf('ERROR: Different list items in positon %d!\n', i)
                    return False
            return True

    elif isinstance(expectedOutputJson, dict):
        if not isinstance(receivedOutputJson, dict):
            failureData['message'] = 'Received output differs in type from expected output.' + " (" + parentPath + ")"
            failureData['expectedElement'] = "Element of the type dict"
            failureData['receivedElement'] = "Element of the type " + receivedOutputJson.__class__.__name__
            printf("Different type: %s and %s\n", expectedOutputJson, receivedOutputJson)
            return False
        for elementKey in expectedOutputJson:
            printf("STEP: Element key %s\n", elementKey)
            if expectedOutputJson[elementKey] is None:
                printf("NONE: Element with key %s is none\n", elementKey)
                continue
            if elementKey not in receivedOutputJson or receivedOutputJson[elementKey] is None:
                failureData['message'] = 'Received output has no key ' + elementKey + '.' + " (" + parentPath + ")"
                failureData['expectedElement'] = "Dict with key " + elementKey
                failureData['receivedElement'] = "None"
                printf('ERROR: Missing key in received json!\n')
                return False
            else:
                if not areSame(expectedOutputJson[elementKey], receivedOutputJson[elementKey], failureData, parentPath + " - " + elementKey):
                    printf('ERROR: Different dict items for key %s!\n', elementKey)
                    return False
        return True

    else:
        eprintf('ERROR: Unsupported type of element %s, type %s!\n', str(expectedOutputJson), expectedOutputJson.__class__.__name__)
        return False
Exemplo n.º 29
0
    if not hasattr(config, 'common_outputs_directory') or not getattr(
            config, 'common_outputs_directory'):
        print('ERROR: common_outputs_directory parameter not defined.')
        exit(1)
    if not hasattr(config, 'common_outputs_workspace') or not getattr(
            config, 'common_outputs_workspace'):
        print('ERROR: common_outputs_workspace parameter not defined.')
        exit(1)
    try:
        workspaceFilePath = os.path.join(
            getattr(config, 'common_outputs_directory'),
            getattr(config, 'common_outputs_workspace'))
        with open(workspaceFilePath, 'r') as workspaceFile:
            workspace = json.load(workspaceFile)
    except IOError:
        eprintf('ERROR: Cannot load workspace file %s\n', workspaceFilePath)
        sys.exit(1)
    if hasattr(config, 'conversation_workspace_name'):
        workspace['name'] = getattr(config, 'conversation_workspace_name')
    else:
        print('WARNING: conversation_workspace_name parameter not defined')

    # credentials
    if not hasattr(config, 'conversation_username') or not getattr(
            config, 'conversation_username'):
        print('ERROR: con_username parameter not defined.')
        exit(1)
    username = getattr(config, 'conversation_username')
    if not hasattr(config, 'conversation_password') or not getattr(
            config, 'conversation_password'):
        print('ERROR: con_password parameter not defined.')
Exemplo n.º 30
0
        setattr(config, 'cloudfunctions_path_to_actions', '/' + '/'.join([getattr(config, 'cloudfunctions_namespace').strip("/"), getattr(config, 'cloudfunctions_package').strip("/")]).strip("/") + '/')

    # load dialogue from XML
    if hasattr(config, 'common_dialog_main'):
        dialogTree = LET.parse(getattr(config, 'common_dialog_main'))
    else:
        dialogTree = LET.parse(sys.stdin)

    # load schema
    schemaDirname, this_filename = os.path.split(os.path.abspath(__file__))
    if not hasattr(config, 'common_schema') or getattr(config, 'common_schema') is None:
        setattr(config, 'common_schema', schemaDirname+'/../data_spec/dialog_schema.xml')
        printf('WARNING: Schema not found, using default path /../data_spec/dialog_schema.xml\n;')
    schemaFile = os.path.join(schemaDirname, getattr(config, 'common_schema'))
    if not os.path.exists(schemaFile):
        eprintf('ERROR: Schema file %s not found.\n', schemaFile)
        exit(1)
    schemaTree = LET.parse(schemaFile)
    schema = LET.XMLSchema(schemaTree)
    validate(dialogTree)

    # process dialog tree
    root = dialogTree.getroot()
    rootGlobal = root
    importNodes(root, config)

    # remove all comments
    removeAllComments(dialogTree)

    # find all node names
    names = findAllNodeNames(dialogTree)