Example #1
0
def extractFileToTmp(zipFilePath: str):
    """
    Extracts the zipFile to the temporary directory of the system.
    """

    zipFile = ZipFile(zipFilePath)

    tmpDir = util.getSystemTmp()
    extractionPath = os.path.join(tmpDir, os.path.basename(zipFilePath))

    logger.debug("Extracting {} to {}".format(zipFile.filename,
                                              extractionPath))
    zipFile.extractall(extractionPath)
    return extractionPath
def createNewBcfFile(name):

    """ Create a new working directory called `name`.

    This working directory contains everything the resulting BCF file will be
    comprised of. To generate the actual BCF file call zipToBcfFile
    """

    logger.debug("Creating new working directory {}".format(name))
    project = p.Project(uuid4(), name)
    newTmpDir = util.getSystemTmp(createNew = True)

    newBcfDir = os.path.join(newTmpDir, name)
    util.setBcfDir(newBcfDir)
    os.mkdir(newBcfDir)
    addElement(project)

    return project
Example #3
0
def readBcfFile(bcfFile: str):
    """ Reads the bcfFile into the memory.

    Before each file is parsed into the class structure it gets validated
    against its corresponding XSD file.  If parsing went successful then a
    value other than a object of type Project is returned.
    """

    logger.debug("Reading file {} and instantiating the data"\
            " model".format(bcfFile))
    tmpDir = util.getSystemTmp()
    (projectSchemaPath, extensionsSchemaPath,\
        markupSchemaPath, versionSchemaPath,\
        visinfoSchemaPath) = util.copySchemas(tmpDir)
    # extensionsSchemaPath is optional and currently not used => does not need
    # to be downloaded.
    if (projectSchemaPath is None or markupSchemaPath is None
            or versionSchemaPath is None or visinfoSchemaPath is None):
        logger.error("One or more schema files could not be downloaded!"\
                "Please try again in a few moments")
        return None

    bcfExtractedPath = extractFileToTmp(bcfFile)

    # before a file gets read into memory it needs to get validated (i.e.:
    # before the corresponding build* function is called, validate with
    # xmlschema)
    ### Check version ###
    versionFilePath = os.path.join(bcfExtractedPath, "bcf.version")
    if not os.path.exists(versionFilePath):
        logger.error(
            "No bcf.version file found in {}. This file is not optional.")
        return None
    error = validateFile(versionFilePath, versionSchemaPath, bcfFile)
    if error != "":
        logger.error(error)
        return None
    version = getVersion(bcfExtractedPath, versionSchemaPath)
    if version not in SUPPORTED_VERSIONS:
        logger.error("BCF version {} is not supported by this plugin. Supported"\
                "versions are: {}".format(version, SUPPORTED_VERSIONS),
                file=sys.stderr)
        return None

    ### Validate project and build ###
    # project.bcfp is optional, but it is necessary for the data model
    proj = Project(UUID(int=0))
    projectFilePath = os.path.join(bcfExtractedPath, "project.bcfp")
    if os.path.exists(projectFilePath):
        error = validateFile(projectFilePath, projectSchemaPath, bcfFile)
        if error != "":
            msg = ("{} is not completely valid. Some parts won't be"\
                    " available.".format(projectFilePath))
            logger.debug(msg)
            logger.error("{}.\n Following the error"\
                    " message:\n{}".format(msg, error))
        proj = buildProject(projectFilePath, projectSchemaPath)

    ### Iterate over the topic directories ###
    topicDirectories = util.getDirectories(bcfExtractedPath)
    for topic in topicDirectories:
        logger.debug("Topic {} gets builded next".format(topic))
        ### Validate all viewpoint files in the directory, and build them ###
        topicDir = os.path.join(bcfExtractedPath, topic)

        markupFilePath = os.path.join(topicDir, "markup.bcf")
        logger.debug("reading topic {}".format(topicDir))
        error = validateFile(markupFilePath, markupSchemaPath, bcfFile)
        if error != "":
            msg = ("markup.bcf of topic {} does not comply with the standard"
                    " of versions {}."\
                    " Some parts won't be available.".format(topic,
                        SUPPORTED_VERSIONS))
            logger.error(msg)
            logger.error("{}\nError:\n{}".format(msg, error))
        markup = buildMarkup(markupFilePath, markupSchemaPath)

        # generate a viewpoint object for all viewpoints listed in the markup
        # object and add them to the ViewpointReference object (`viewpoint`)
        # inside markup
        for vpRef in markup.viewpoints:
            vpPath = os.path.join(topicDir, vpRef.file.uri)
            try:
                # if some required element was not found, indicated by a key
                # error then skip the viewpoint
                vp = buildViewpoint(vpPath, visinfoSchemaPath)
            except KeyError as err:
                logger.error("{} is required in a viewpoint file."
                    " Viewpoint {}/{} is skipped"\
                        "".format(str(err), topic, vpRef.file))
                continue
            else:
                vpRef.viewpoint = vp

        markup.containingObject = proj
        # add the finished markup object to the project
        proj.topicList.append(markup)

    util.setBcfDir(bcfExtractedPath)
    logger.debug("BCF file is read in and open in"\
            " {}".format(bcfExtractedPath))
    return proj
Example #4
0
    pass
else:
    FREECAD = True
    if FreeCAD.GuiUp:
        FreeCAD.Console.PrintMessage("set util.GUI\n")
        import FreeCADGui as FGui
        GUI = True

frontend = None
if not check_dependencies():
    raise ImportError

# delete temporary artifacts
import util
util.deleteTmp()

# create working directory
path = util.getSystemTmp()
logfile = os.path.join(path, LOGFILE)

# generate config for root logger
logHandlers = [getFileHandler(logfile)]
if FREECAD:
    logHandlers.append(getFreeCADHandler())
else:
    logHandlers.append(getStdoutHandler())
logging.basicConfig(level=logging.INFO, handlers=logHandlers)

# for nonGUI-mode import __all__ of pI into this namespace
from programmaticInterface import *
def addElement(element):

    """ Adds a new element to the correct file in the working directory.

    In this context an element can be a simple or complex xml element as well as
    just an attribute of an element that was added to the datamodel and shall
    now be added to the file as well.
    Both additions have the following approach in common:
        - the current file is read into an xml.etree.ElementTree structure.
        - this structure is updated with the new values
        - the old file is overwritten with the updated xml.etree.ElementTree
          structure
    For the addition of attributes it is assumed that the containing element
    already exists in the file. This element is searched for and expanded by the
    new attribute.
    For the addition of elements the parent element is searched for, and in the
    predefined sequence of the parent the right insertion index is looked up,
    since the element cant just be appended, otherwise it would not be schema
    conform anymore.
    """

    logger.debug("Adding element {} to the working"\
            " directory.".format(element.__class__))
    addToProject = False
    # filename in which `element` will be found
    fileName = getFileOfElement(element)
    if not fileName:
        raise ValueError("{} is not applicable to be added to anyone"\
            "file".format(element.xmlName))
    elif fileName == projectFileName:
        addToProject = True

    if fileName is None:
        raise NotImplementedError("Writing of bcf.version"\
                " is not supported")

    bcfPath = util.getBcfDir()
    topicPath = ""
    if not addToProject:
        topicDir = getTopicDir(element)
        if not topicPath and addToProject:
            raise RuntimeError("Element {} could not be associated to any topic."\
                "This may be the case if properties in project.bcfp should be"\
                "modified, which is currently not implemented!".format(str(element)))
        topicPath = os.path.join(bcfPath, topicDir)

    filePath = ""
    if not addToProject:
        filePath = os.path.join(topicPath, fileName)

    # file path shall only be set if an element shall be added to project.bcfp
    # and not project.bcfp shall be created in the first place
    elif addToProject and not isinstance(element, p.Project):
        filePath = os.path.join(bcfPath, fileName)

    logger.debug("Element is going to be added to"\
            " {}".format(filePath))
    if isinstance(element, p.Project):
        workDir = util.getSystemTmp()
        logger.debug("Creating new project in {}".format(workDir))
        _createProject(element, workDir)
        return

    # adds a complete new topic folder to the zip file
    if isinstance(element, m.Markup):
        logger.debug("Creating new markup file in"\
            " {}".format(topicPath))
        _createMarkup(element, topicPath)
        return

    xmltree = ET.parse(filePath)
    xmlroot = xmltree.getroot()

    # different handling for attributes and elements
    if isinstance(element, p.Attribute):
        logger.debug("Element is added as attribute.")
        xmlroot = _addAttribute(element, xmlroot)

    else:
        logger.debug("Element is added as XML node.")
        xmlroot = _addElement(element, xmlroot)

    # generate viewpoint.bcfv file for added viewpoint
    if (isinstance(element, m.ViewpointReference) and
            element.viewpoint is not None and
            element.viewpoint.state == iS.State.States.ADDED):

        logger.debug("Creating new viewpoint file in"\
                " {}".format(topicPath))
        _createViewpoint(element, topicPath)

    writeXMLFile(xmlroot, filePath)