Source code for core.backend.scan

"""
VIKI: more than a GUI for ROS, https://github.com/UT-RAM/viki 
version: 0.2 - Alice
copyright: Robin Hoogervorst, Alex Kamphuis, Cees Trouwborst, 2016 
licensed under the MIT License
"""

"""Provides :func:`getAvailableModules`.
"""

import xml.dom.minidom
import os
import re
import traceback
from objects import *
from helpers import *


[docs]def getAvailableModules(viki_config): """Return a list of modules available in the framework at this moment. #. Run through the entire project tree searching for files called 'viki.xml'. #. Create an abstraction from each .xml file as objects from :mod:`core.aero.objects`. #. Put abstraction in a list #. Return list when done. """ available_mods = [] # START FILE LOOP rootDir = os.path.expanduser(viki_config.get_root_module_dir()) for dirName, subdirList, fileList in os.walk(rootDir): for fName in fileList: if fName == 'viki.xml': try: fPath = dirName + '/' + fName f = open(fPath) fLine = f.readlines()[0] if re.search('VIKI_MODULE', fLine) is not None: # Get DOM dom = xml.dom.minidom.parse(fPath) moddom = dom.getElementsByTagName('module')[0] # Skip if the module already exists modname = moddom.attributes['id'].value existingMod = findModuleById(available_mods, modname) if existingMod is not None: print "Module ", modname, " (in ", fPath, ") already exists (in ", mod.path, ") and is therefore skipped." continue mod = Module(moddom.attributes['type'].value, modname) # META DATA meta = dom.getElementsByTagName('meta') if not meta: print "No meta data present" else: # We can have multiple META sections for metaelem in meta: # Check if there are childnodes if len(getElements(metaelem)) > 0: for metachild in getElements(metaelem): mod.addMeta(metachild.tagName.lower(), metachild.firstChild.nodeValue) else: print "Empty meta data section in document" # DEPENDENCIES dependencies = dom.getElementsByTagName('dependencies') if len(dependencies) == 1: for depchild in getElements(dependencies[0]): if depchild.tagName == "depends": src = "" type = "apt-get" if depchild.hasAttribute('src'): src = depchild.attributes['src'].value if depchild.hasAttribute('type'): type = depchild.attributes['type'].value mod.addPackageDependency(depchild.firstChild.nodeValue, type, src) # MODULE PATH mod.setPath(fPath) # MODULE INPUTS gInputElement = getElementsOnFirstLevel(moddom, 'inputs') if gInputElement: gInputs = getElements(gInputElement[0]) for gInput in gInputs: oType = gInput.attributes['type'].value oName = gInput.attributes['name'].value oLink = gInput.attributes['link'].value oMessageType = gInput.attributes['message_type'].value oRequired = gInput.attributes['required'].value interface = Interface(oType, oName, oMessageType, oRequired, oLink) mod.addInput(interface) # MODULE OUTPUTS gOutputElement = getElementsOnFirstLevel(moddom, 'outputs') if gOutputElement: gOutputs = getElements(gOutputElement[0]) for gOutput in gOutputs: oType = gOutput.attributes['type'].value oName = gOutput.attributes['name'].value oLink = gOutput.attributes['link'].value oMessageType = gOutput.attributes['message_type'].value oRequired = gOutput.attributes['required'].value interface = Interface(oType, oName, oMessageType, oRequired, oLink) mod.addOutput(interface) # Instead of looping over userinputs, controllers, etc. separately, go find the executables to add flexibility in the classes executables = dom.getElementsByTagName('executable') for executable in executables: executableId = executable.attributes['id'].value executablePkg = executable.attributes['pkg'].value executableExec = executable.attributes['exec'].value executableArg = getOptionalAttribute(executable, 'args') executableObject = Executable(executableId, executablePkg, executableExec) if executableArg is not None: executableObject.setArguments(executableArg) # EXECUTABLE INPUTS gInputElement = getElementsOnFirstLevel(executable, 'inputs') if gInputElement: gInputs = getElements(gInputElement[0]) for gInput in gInputs: oType = gInput.attributes['type'].value oName = gInput.attributes['name'].value oMessageType = gInput.attributes['message_type'].value oRequired = getOptionalAttribute(gInput, 'required') oNamespace = "base" if gInput.hasAttribute('namespace'): oNamespace = gInput.attributes['namespace'].value interface = Interface(oType, oName, oMessageType, oRequired, namespace=oNamespace) executableObject.addInput(interface) # EXECUTABLE OUTPUTS gOutputElement = getElementsOnFirstLevel(executable, 'outputs') if gOutputElement: gOutputs = getElements(gOutputElement[0]) for gOutput in gOutputs: oType = gOutput.attributes['type'].value oName = gOutput.attributes['name'].value oMessageType = gOutput.attributes['message_type'].value oRequired = getOptionalAttribute(gOutput, 'required') oNamespace = "base" if gOutput.hasAttribute('namespace'): oNamespace = gOutput.attributes['namespace'].value interface = Interface(oType, oName, oMessageType, oRequired, namespace=oNamespace) executableObject.addOutput(interface) # PARAMS ParameterElement = getElementsOnFirstLevel(executable, 'params') if ParameterElement: Parameters = getElements(ParameterElement[0]) for aParameter in Parameters: aName = aParameter.attributes['name'].value aType = getOptionalAttribute(aParameter, 'type') if aType not in ['str', 'int', 'double', 'bool']: print "[WARNING] - Type of parameter {} in {} has no valid type".format(aName, executableId) aDefault = getOptionalAttribute(aParameter, 'default') parameter = Parameter(aName, aType, default=aDefault) executableObject.addParameter(parameter) mod.addExecutable(executableObject) # Internal connections ConfigElements = getElementsOnFirstLevel(moddom, 'configuration') if ConfigElements: for ConfigElement in ConfigElements: connections_to_add = getElementsOnFirstLevel(ConfigElement, 'connect') if connections_to_add: for connection_to_add in connections_to_add: internal_interface = Internal_Interface(connection_to_add.attributes['publisher'].value, connection_to_add.attributes['listener'].value) mod.addIntConnect(internal_interface) available_mods.append(mod) except Exception as e: print "Skipped adding '" + fPath + "' because it is a broken file. Error thrown was:" print traceback.format_exc() # END FILE LOOP return available_mods