예제 #1
0
    def openDocument(self, _fileName):
        fileName = _fileName

        if a2plib.PYVERSION == 3:
            fileName = a2plib.to_str(fileName)

        self.clear()

        # got a fileName != None ?
        if fileName is None:
            print(u"fcDocumentReader: failed to open file with None name!")
            return

        # check whether file exists or not...
        if not os.path.exists(fileName):
            print(
                u"fcDocumentReader: file {} does not exist!".format(fileName))
            return

        # check for fcstd file
        if not fileName.lower().endswith(a2plib.to_str('.fcstd')):
            print(u"fcDocumentReader: file {} is no FCStd file!".format(
                fileName))
            return

        # decompress the file
        f = zipfile.ZipFile(fileName, 'r')
        xml = f.read('Document.xml')
        f.close()
        self.successfulOpened = True
        #
        #self.xmlLines = xml.split("\r\n") #Windows
        self.xmlLines = xml.split(b'\r\n')  #Windows
        if len(self.xmlLines) <= 1:
            self.xmlLines = xml.split(b"\n")  #Linux
        del (xml)

        # remove not needed data above first section <objects name=...
        idx = 0
        for line in self.xmlLines:
            if line.lstrip(b' ').startswith(b'<Object name'):
                break
            else:
                idx += 1
        self.xmlLines = self.xmlLines[idx:]  #reduce list size instantly

        while len(self.xmlLines) > 0:
            if not self.xmlLines[0].strip(b' ').startswith(b'<Object name'):
                break
            ob = simpleXMLObject()
            self.xmlLines = ob.initialize(self.xmlLines)
            self.objects.append(ob)

        # remove not needed objects
        tmp = []
        for ob in self.objects:
            if ob.isA2pObject() or ob.isSpreadSheet():
                tmp.append(ob)
        self.objects = tmp
예제 #2
0
    def visualizeHierarchy(self):
        '''
        generate a html file with constraints structure.
        
        The html file is in the same folder 
        with the same filename of the assembly
        '''
        out_file = os.path.splitext(self.doc.FileName)[0] + '_asm_hierarchy.html'
        Msg("Writing visual hierarchy to: {}\n".format(out_file))
        f = open(out_file, "w")

        f.write("<!DOCTYPE html>\n")
        f.write("<html>\n")
        f.write("<head>\n")
        f.write('    <meta charset="utf-8">\n')
        f.write('    <meta http-equiv="X-UA-Compatible" content="IE=edge">\n')
        f.write('    <title>A2P assembly hierarchy visualization</title>\n')
        f.write("</head>\n")
        f.write("<body>\n")
        f.write('<div class="mermaid">\n')

        f.write("graph TD\n")
        for rig in self.rigids:
            rigLabel = a2plib.to_str(rig.label).replace(u' ',u'_')
            # No children, add current rogod as a leaf entry
            if len(rig.childRigids) == 0:
                message = u"{}\n".format(rigLabel)
                if a2plib.PYVERSION < 3:
                    f.write(a2plib.to_bytes(message))
                else:
                    f.write(message)
            else:
                # Rigid have children, add them based on the dependency list
                for d in rig.dependencies:
                    if d.dependedRigid in rig.childRigids:
                        dependedRigLabel = a2plib.to_str(d.dependedRigid.label).replace(u' ',u'_')
                        if rig.fixed:
                            message = u"{}({}<br>*FIXED*) -- {} --> {}\n".format(rigLabel, rigLabel, d.Type, dependedRigLabel)
                            if a2plib.PYVERSION < 3:
                                f.write(a2plib.to_bytes(message))
                            else:
                                f.write(message)
                        else:
                            message = u"{} -- {} --> {}\n".format(rigLabel, d.Type, dependedRigLabel)
                            if a2plib.PYVERSION < 3:
                                f.write(a2plib.to_bytes(message))
                            else:
                                f.write(message)

        f.write("</div>\n")
        f.write('    <script src="https://unpkg.com/[email protected]/dist/mermaid.js"></script>\n')
        f.write("    <script>\n")
        f.write('        mermaid.initialize({startOnLoad: true});\n')
        f.write("    </script>\n")
        f.write("</body>")
        f.write("</html>")
        f.close()
예제 #3
0
def createPartList(
        importPath,
        parentAssemblyDir,
        partListEntries,
        recursive=False
        ):
    '''
    Extract quantities and descriptions of assembled parts from
    document.xml
    Is able to analyse subassemblies by recursion
    
    It works with a dict. Structure of an entry is:
    filename: [Quantity,[information,information,....] ]
    '''
    fileNameInProject = a2plib.findSourceFileInProject(
        importPath,
        parentAssemblyDir
        )
    workingDir,basicFileName = os.path.split(fileNameInProject)
    
    docReader1 = FCdocumentReader()
    docReader1.openDocument(fileNameInProject)
    
    for ob in docReader1.getA2pObjects():
        # skip converted parts...
        if a2plib.to_str(ob.getA2pSource()) == a2plib.to_str('converted'): continue
        
        if ob.isSubassembly() and recursive:
            partListEntries = createPartList(
                                        ob.getA2pSource(),
                                        workingDir,
                                        partListEntries,
                                        recursive
                                        )
            
        # Process information of this a2p object
        if not ob.isSubassembly() or not recursive:
            # Try to get spreadsheetdata _PARTINFO_ from linked source
            linkedSource1 = ob.getA2pSource()
            linkedSource = a2plib.findSourceFileInProject( #this returns unicode on py2 systems!
                            linkedSource1,
                            workingDir
                            )
            if linkedSource == None:
                print(u"BOM ERROR: Could not open sourcefile {}".format(linkedSource1))
                continue
            # Is it already processed minimum one time ?
            entry = partListEntries.get(linkedSource,None)
            if entry != None:
                partListEntries.get(linkedSource)[0]+=1 #count sourcefile usage
                continue # only needed to count imports of this file, information exists yet

            # There is no entry in dict, need to read out information from importFile...
            docReader2 = FCdocumentReader()
            docReader2.openDocument(linkedSource)

            # Initialize a default parts information...
            partInformation = []
            for i in range(0,len(PARTLIST_COLUMN_NAMES)):
                partInformation.append("*")
                
            # if there is a proper spreadsheet, then read it...
            for ob in docReader2.getSpreadsheetObjects():
                
                sheetName = PARTINFORMATION_SHEET_NAME
                if a2plib.PYVERSION > 2:
                    sheetName = a2plib.to_bytes(PARTINFORMATION_SHEET_NAME)
                    
                if ob.name == sheetName:
                    cells = ob.getCells()
                    for addr in cells.keys():
                        if addr[:1] == b'B': #column B contains the data, A only the titles
                            idx = int(addr[1:])-1
                            if idx < len(PARTLIST_COLUMN_NAMES): # don't read further!
                                partInformation[idx] = cells[addr]
            # last entry of partinformations is reserved for filename
            partInformation[-1] = os.path.split(linkedSource)[1] #without complete path...

            # put information to dict and count usage of sourcefiles..
            entry = partListEntries.get(linkedSource,None)
            if entry == None:
                partListEntries[linkedSource] = [
                    1,
                    partInformation
                    ]
            else:
                partListEntries.get(linkedSource)[0]+=1 #count sourcefile usage
                
    return partListEntries
예제 #4
0
 def scanForProperties(self):
     sourceFileFound = False
     a2pVersionFound = False
     subAssemblyImportFound = False
     timeLastImportFound = False
     spreadSheetCellsFound = False
     a2pObjectTypeFound = False
     
     numLines = len(self.xmlDefs)
     # Readout object's name and save it (1rst line)
     if numLines > 0:
         line = self.xmlDefs[0]
         segments = line.split(b'"')
         self.name = segments[1]
     idx = 0
     while idx<numLines:
         line = self.xmlDefs[idx]
         
         if not sourceFileFound and line.startswith(b'<Property name="sourceFile"'):
             idx+=1
             line = self.xmlDefs[idx]
             segments = line.split(b'"')
             fileName = segments[1]
             self.propertyDict[b'sourceFile'] = a2plib.to_str(fileName)
             sourceFileFound = True
             
         elif not a2pVersionFound and line.startswith(b'<Property name="a2p_Version"'):
             idx+=1
             line = self.xmlDefs[idx]
             segments = line.split(b'"')
             a2pVersion = segments[1]
             self.propertyDict[b'a2p_Version'] = a2plib.to_str(a2pVersion)
             a2pVersionFound = True
             
         elif not a2pVersionFound and line.startswith(b'<Property name="assembly2Version"'):
             idx+=1
             line = self.xmlDefs[idx]
             segments = line.split(b'"')
             a2pVersion = segments[1]
             self.propertyDict[b'a2p_Version'] = a2plib.to_str(a2pVersion)
             a2pVersionFound = True
             
         # for very old a2p versions do additionally...
         elif not subAssemblyImportFound and line.startswith(b'<Property name="subassemblyImport"'):
             idx+=1
             line = self.xmlDefs[idx]
             segments = line.split(b'"')
             tmp = segments[1]
             val = True
             if tmp == b"false":
                 val = False
             self.propertyDict[b'subassemblyImport'] = val
             subAssemblyImportFound = True
             
         elif not timeLastImportFound and line.startswith(b'<Property name="timeLastImport"'):
             idx+=1
             line = self.xmlDefs[idx]
             segments = line.split(b'"')
             tmp = segments[1]
             floatVal = float(tmp)
             self.propertyDict[b'timeLastImport'] = floatVal
             timeLastImportFound = True
             
         elif not spreadSheetCellsFound and line.startswith(b'<Property name="cells" type="Spreadsheet::PropertySheet"'):
             spreadSheetCellsFound = True
             idx += 2
             cellDict = {}
             while True:
                 line = self.xmlDefs[idx]
                 if line.startswith(b'</Cells>'): break
                 if line.startswith(b'<Cell address="'):
                     cellAdress,cellContent = self.parseCellLine(line)
                     cellDict[cellAdress] = a2plib.to_str(cellContent)
                 idx += 1
             self.propertyDict[b'cells'] = cellDict
             
         elif not a2pObjectTypeFound and line.startswith(b'<Property name="objectType"'):
             idx+=1
             line = self.xmlDefs[idx]
             segments = line.split(b'"')
             objectType = segments[1]
             self.propertyDict[b'objectType'] = a2plib.to_bytes(objectType)
             a2pObjectTypeFound = True
             
         idx+=1
     self.xmlDefs = [] # we are done, free memory...