def test_01(self): """Test_PathSplit.test_01(): pathSplit()""" self.assertEqual(['.'], HtmlUtils.pathSplit('')) self.assertEqual(['spam/', 'eggs.lis'], HtmlUtils.pathSplit('spam/eggs.lis')) self.assertEqual(['../', 'spam/', 'eggs.lis'], HtmlUtils.pathSplit('../spam/eggs.lis')) self.assertEqual(['../', 'eggs.lis'], HtmlUtils.pathSplit('../spam/../eggs.lis')) self.assertEqual(['../', 'chips/', 'eggs.lis'], HtmlUtils.pathSplit('../spam/../chips/eggs.lis'))
def test_02(self): """Test_writeFileListTrippleAsTable.test_02(): writeFileListTrippleAsTable() - Single directory list""" myFileNameS = [ 'spam/beans.lis', 'spam/chips.lis', 'spam/eggs.lis', ] myFileLinkS = [(f, HtmlUtils.retHtmlFileName(f), 'Link text {:d}'.format(i)) for i, f in enumerate(myFileNameS)] myF = io.StringIO() with XmlWrite.XhtmlStream(myF) as myS: HtmlUtils.writeFileListTrippleAsTable(myS, myFileLinkS, {}, False) # print() # print(myF.getvalue()) # self.maxDiff = None self.assertEqual(myF.getvalue(), """<?xml version='1.0' encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml"> <table> <tr> <td rowspan="3">spam/</td> <td> <a href="beans.lis_2cd7aad2a1a03013720d9cc5d83b860c.html">Link text 0</a></td> </tr> <tr> <td> <a href="chips.lis_78c24a9e68057387b3f7c7de7f57385d.html">Link text 1</a></td> </tr> <tr> <td> <a href="eggs.lis_afc193e8de9a2e06454b4bf92d5fefd8.html">Link text 2</a></td> </tr> </table> </html> """)
def test_01(self): """Test_writeFileListTrippleAsTable.test_01(): writeFileListTrippleAsTable() - Single file list""" myFileNameS = [ '0eggs.lis', '1chips.lis', '2beans.lis', ] myFileLinkS = [(f, HtmlUtils.retHtmlFileName(f), 'Link text {:d}'.format(i)) for i, f in enumerate(myFileNameS)] myF = io.StringIO() with XmlWrite.XhtmlStream(myF) as myS: HtmlUtils.writeFileListTrippleAsTable(myS, myFileLinkS, {}, False) # print() # print(myF.getvalue()) # self.maxDiff = None # print(myFileLinkS) self.assertEqual(myF.getvalue(), """<?xml version='1.0' encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml"> <table> <tr> <td> <a href="0eggs.lis_4656d29aa36ca0c168a10dd3ffe2c9fa.html">Link text 0</a></td> </tr> <tr> <td> <a href="1chips.lis_6cb5a1758e21dad3dba0cc4a53d91c31.html">Link text 1</a></td> </tr> <tr> <td> <a href="2beans.lis_961d8a2ab0ecf325e12f11c8bdbbf817.html">Link text 2</a></td> </tr> </table> </html> """)
def _writeMacroReferencesTable(theS, theFlcS): """Writes all the references to a file/line/col in a rowspan/colspan HTML table with links to the position in the HTML representation of the file that references something. This uses a particular design pattern that uses a DictTree to sort out the rows and columns. In this case the DictTree values are lists of pairs (href, nav_text) where nav_text is the line-col of the referencing file.""" myFileLineColS = [] # This removes duplicates, it is a list of (fileId, lineNum, colNum). # If an include file is included N times there will be N-1 duplicate entries # for the header guard macro otherwise. hasSeen = [] for aFlc in theFlcS: ident = (aFlc.fileId, aFlc.lineNum, aFlc.colNum) if ident not in hasSeen: myFileLineColS.append(( aFlc.fileId, ( HtmlUtils.retHtmlFileLink(aFlc.fileId, aFlc.lineNum), # Navigation text '%d-%d' % (aFlc.lineNum, aFlc.colNum), ), )) hasSeen.append(ident) if len(myFileLineColS) > 0: HtmlUtils.writeFilePathsAsTable('list', theS, myFileLineColS, 'filetable', _tdFilePathCallback)
def _writeMacroDependenciesTable(theS, theEnv, theAdjList, theItu): """Writes all the macro dependencies to a rowspan/colspan HTML that references something. table with links to the position in the HTML representation of the file This uses a particular design pattern that uses a DictTree to sort out the rows and columns. In this case the DictTree values are lists of pairs (href, nav_text) where nav_text is the line_col of the referencing file.""" myDt = DictTree.DictTreeHtmlTable('list') for branch in theAdjList.branches(): # I might depend on a macro (that is referenced) but I am not referenced. if theEnv.macro(branch[-1]).refCount > 0: href = '%s#%s' % ( _macroHistoryRefName(theItu), _retMacroId(theEnv.macro(branch[-1]), 0), ) else: href = '%s#%s' % ( _macroHistoryNorefName(theItu), _retMacroId(theEnv.macro(branch[-1]), 0), ) # TODO: theIntOccurence is set 0 here myDt.add(branch, ( href, branch[-1], )) # Now iterate with rowspan/colspan if len(myDt) > 0: HtmlUtils.writeDictTreeAsTable(theS, myDt, tableAttrs={'class': "filetable"}, includeKeyTail=False)
def _writeTrMacro(theS, theHtmlPath, theMacro, theIntOccurence, theStartLetter, retMap): """Write the macro as a row in the general table. theMacro is a PpDefine object. theStartLetter is the current letter we are writing ['A', 'B', ...] which writes an anchor at the beginning of each letter section.""" with XmlWrite.Element(theS, 'tr'): if theMacro.identifier[0] != theStartLetter: theStartLetter = theMacro.identifier[0] _writeTdMacro(theS, theMacro, theStartLetter, theIntOccurence) else: _writeTdMacro(theS, theMacro, '', theIntOccurence) if theMacro.identifier not in retMap: # Add to the return value retMap[theMacro.identifier] = '%s#%s' \ % ( os.path.basename(theHtmlPath), _retMacroId(theMacro, theIntOccurence), ) with XmlWrite.Element(theS, 'td'): HtmlUtils.writeHtmlFileLink( theS, theMacro.fileId, theMacro.line, '%s#%d' % (theMacro.fileId, theMacro.line), 'file_decl') _writeTdRefCount(theS, theMacro) _writeTdMonospace(theS, str(theMacro.isCurrentlyDefined)) return theStartLetter
def visitPre(self, theCcgNode, theDepth): """Pre-traversal call with a CppCondGraphNode and the integer depth in the tree.""" self._hs.characters(self.PAD_STR * theDepth) if theCcgNode.state: myCssClass = 'CcgNodeTrue' else: myCssClass = 'CcgNodeFalse' with XmlWrite.Element(self._hs, 'span', {'class' : myCssClass}): self._hs.characters('#%s' % theCcgNode.cppDirective) if theCcgNode.constExpr is not None: self._hs.characters(' %s' % theCcgNode.constExpr) self._hs.characters(' ') self._hs.characters(' /* ') HtmlUtils.writeHtmlFileLink( self._hs, theCcgNode.fileId, theCcgNode.lineNum, os.path.basename(theCcgNode.fileId), theClass=None, ) self._hs.characters(' */') #with XmlWrite.Element(self._hs, 'span', {'class' : 'file'}): # self._hs.characters(' [%s]' % theCcgNode.fileId) self._hs.characters('\n')
def test_01(self): """Test_writeFileListTrippleAsTable.test_01(): writeFileListTrippleAsTable() - Single file list""" myFileNameS = [ '0eggs.lis', '1chips.lis', '2beans.lis', ] myFileLinkS = [(f, HtmlUtils.retHtmlFileName(f), 'Link text {:d}'.format(i)) for i, f in enumerate(myFileNameS)] myF = io.StringIO() with XmlWrite.XhtmlStream(myF) as myS: HtmlUtils.writeFileListTrippleAsTable(myS, myFileLinkS, {}, False) # print() # print(myF.getvalue()) # self.maxDiff = None # print(myFileLinkS) self.assertEqual( myF.getvalue(), """<?xml version='1.0' encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml"> <table> <tr> <td> <a href="0eggs.lis_55d1c28c70fa11242791f484339eb1be.html">Link text 0</a></td> </tr> <tr> <td> <a href="1chips.lis_9d8f17f73fd3f595dcdc0d6cb43efee2.html">Link text 1</a></td> </tr> <tr> <td> <a href="2beans.lis_c191c76d1f99127750d4f05f0d47e101.html">Link text 2</a></td> </tr> </table> </html> """)
def _writeMacroHistory(theS, theMacro, theOmitFiles, theIntOccurence): """Writes out the macro history from a PpDefine object. theMacro - a PpDefine() object. theOmitFiles - a list of pseudo files not to link to e.g. ['Unnamed Pre-include',]. :param theS: The HTML stream. :type theS: :py:class:`cpip.util.XmlWrite.XhtmlStream` :param theMacro: The macro. :type theMacro: :py:class:`cpip.core.PpDefine.PpDefine` :param theOmitFiles: A list of pseudo files not to link to e.g. ['Unnamed Pre-include',]. :type theOmitFiles: ``list([str])`` :param theIntOccurence: The occurence of the macro which will be added to the link ID. :type theIntOccurence: ``int`` :returns: ``NoneType`` """ anchorName = _retMacroId(theMacro, theIntOccurence) # Write out the macro title with XmlWrite.Element(theS, 'h3'): with XmlWrite.Element(theS, 'a', {'name': anchorName}): theS.characters('%s [References: %d] Defined? %s' \ % ( theMacro.identifier, theMacro.refCount, str(theMacro.isCurrentlyDefined) ) ) with XmlWrite.Element(theS, 'p'): anchorName = _writeMacroDefinitionAndAnchor(theS, theMacro, theIntOccurence) with XmlWrite.Element(theS, 'p'): with XmlWrite.Element(theS, 'tt'): theS.characters('defined @ ') # theS.literal(' ') # theS.characters('@ ') HtmlUtils.writeHtmlFileLink(theS, theMacro.fileId, theMacro.line, '%s#%d' % (theMacro.fileId, theMacro.line), 'file_decl') _writeMacroReferencesTable(theS, theMacro.refFileLineColS) # If inactive then state where #undef'd if not theMacro.isCurrentlyDefined: with XmlWrite.Element(theS, 'p'): with XmlWrite.Element(theS, 'tt'): theS.characters('undef\'d @ ') # theS.literal(' ') # theS.characters('@ ') HtmlUtils.writeHtmlFileLink( theS, theMacro.undefFileId, theMacro.undefLine, '%s#%d' % (theMacro.undefFileId, theMacro.undefLine), 'file_decl')
def test_02(self): """Test_retHtmlFileName.test_02(): retHtmlFileLink() - basic functionality.""" self.assertEqual('_85815d8fcaf4100c893e42ecf798ee68.html#4', HtmlUtils.retHtmlFileLink('', 4)) self.assertEqual('foo.lis_a2264fb27d01482d85fb07d540d99d29.html#4', HtmlUtils.retHtmlFileLink('foo.lis', 4)) myPathStr = 'a very long path that goes on and on and on and you think that it will never ever stop spam.lis' myPath = os.path.join(*myPathStr.split()) self.assertEqual('a/very/long/path/that/goes/on/and/on/and/on/and/you/think/that/it/will/never/ever/stop/spam.lis', myPath) self.assertEqual( 'spam.lis_eb53aeb1072ab90b9ba0304c5e2b6fd9.html#4', HtmlUtils.retHtmlFileLink(myPath, 4), )
def test_03(self): """TestXhtmlWrite.test_03(): writeHtmlFileAnchor().""" myF = io.StringIO() with XmlWrite.XhtmlStream(myF) as myS: HtmlUtils.writeHtmlFileAnchor(myS, 47, theText='Navigation text') # print() # print(myF.getvalue()) self.assertEqual(myF.getvalue(), """<?xml version='1.0' encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml"> <a name="47" />Navigation text</html> """)
def test_02(self): """Test_retHtmlFileName.test_02(): retHtmlFileLink() - basic functionality.""" self.assertEqual('_5058f1af8388633f609cadb75a75dc9d.html#4', HtmlUtils.retHtmlFileLink('', 4)) self.assertEqual('foo.lis_7cc7c6edbd4c065f2406358e9211d9eb.html#4', HtmlUtils.retHtmlFileLink('foo.lis', 4)) myPathStr = 'a very long path that goes on and on and on and you think that it will never ever stop spam.lis' myPath = os.path.join(*myPathStr.split()) self.assertEqual( 'a/very/long/path/that/goes/on/and/on/and/on/and/you/think/that/it/will/never/ever/stop/spam.lis', myPath) self.assertEqual( 'spam.lis_899456b1d7f9e35f3f5338b5883ae262.html#4', HtmlUtils.retHtmlFileLink(myPath, 4), )
def _writeMacroDependenciesTable(theS, theEnv, theAdjList, theItu): """Writes all the macro dependencies to a rowspan/colspan HTML that references something. table with links to the position in the HTML representation of the file This uses a particular design pattern that uses a DictTree to sort out the rows and columns. In this case the DictTree values are lists of pairs ``(href, nav_text)`` where ``nav_text`` is the line_col of the referencing file. :param theS: HTML stream. :type theS: :py:class:`cpip.util.XmlWrite.XhtmlStream` :param theEnv: The macro environment. :type theEnv: :py:class:`cpip.core.MacroEnv.MacroEnv` :param theAdjList: Dependency adjacency list. :type theAdjList: :py:class:`cpip.util.Tree.Tree` :param theItu: The Initial Translation Unit (ITU). :type theItu: ``str`` :returns: ``NoneType`` """ myDt = DictTree.DictTreeHtmlTable('list') for branch in theAdjList.branches(): # I might depend on a macro (that is referenced) but I am not referenced. if theEnv.macro(branch[-1]).refCount > 0: href = '%s#%s' % ( _macroHistoryRefName(theItu), _retMacroId(theEnv.macro(branch[-1]), 0), ) else: href = '%s#%s' % ( _macroHistoryNorefName(theItu), _retMacroId(theEnv.macro(branch[-1]), 0), ) # TODO: theIntOccurence is set 0 here myDt.add(branch, ( href, branch[-1], )) # Now iterate with rowspan/colspan if len(myDt) > 0: HtmlUtils.writeDictTreeAsTable(theS, myDt, tableAttrs={'class': "filetable"}, includeKeyTail=False)
def __init__(self, theItu, theHtmlDir, keepGoing=False, macroRefMap=None, cppCondMap=None, ituToTuLineSet=None): """Takes an input source file and an output directory. theItu - The original source file path (or file like object for the input). theHtmlDir - The output directory for the HTML or a file-like object for the output keepGoing - Bool, if True raise on error. macroRefMap - Map of {identifier : href_text, ...) to link to macro definitions. ituToTuLineSet - Set of integer line numbers which are lines that can be linked to the translation unit representation.""" try: # Assume string or unicode first self._fpIn = theItu self._ituFileObj = open(self._fpIn) except TypeError: self._fpIn = 'Unknown' self._ituFileObj = theItu if isinstance(theHtmlDir, str): if not os.path.exists(theHtmlDir): os.makedirs(theHtmlDir) self._fOut = open(os.path.join(theHtmlDir, HtmlUtils.retHtmlFileName(self._fpIn)), 'w') else: self._fOut = theHtmlDir self._keepGoing = keepGoing # Map of {identifier : href_text, ...) to link to macro definitions. self._macroRefMap = macroRefMap or {} self._cppCondMap = cppCondMap self._ituToTuLineSet = ituToTuLineSet # Start at 0 as this gets incremented before write self._lineNum = 0 self._convert()
def test_01(self): """TestXhtmlWrite.test_01(): writeHtmlFileLink() simple.""" myF = io.StringIO() with XmlWrite.XhtmlStream(myF) as myS: HtmlUtils.writeHtmlFileLink(myS, 'spam/eggs/chips.lis', 47, theText='Navigation text', theClass=None) # print() # print(myF.getvalue()) # self.maxDiff = None self.assertEqual("""<?xml version='1.0' encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml"> <a href="chips.lis_5e410d3de8868d056cd4d3367f91e769.html#47">Navigation text</a> </html> """, myF.getvalue(), )
def test_03(self): """Test_writeFileListAsTable.test_03(): writeFileListAsTable() - Multiple directory list""" myFileNameS = [ 'spam/eggs.lis', 'spam/chips.lis', 'spam/fishfingers/beans.lis', 'spam/fishfingers/peas.lis', ] myFileLinkS = [(f, HtmlUtils.retHtmlFileName(f)) for f in myFileNameS] myF = io.StringIO() with XmlWrite.XhtmlStream(myF) as myS: HtmlUtils.writeFileListAsTable(myS, myFileLinkS, {}, False) # print() # print(myF.getvalue()) # self.maxDiff = None self.assertEqual( myF.getvalue(), """<?xml version='1.0' encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml"> <table> <tr> <td rowspan="4">spam/</td> <td colspan="2"> <a href="chips.lis_cf88bd52fd64d0ee6dd7f9f7d465d22b.html">chips.lis</a> </td> </tr> <tr> <td colspan="2"> <a href="eggs.lis_bc8a04943b99ef250322263f7f263272.html">eggs.lis</a> </td> </tr> <tr> <td rowspan="2">fishfingers/</td> <td> <a href="beans.lis_a50e730e7b0104f5a34f3aca74fd03b0.html">beans.lis</a> </td> </tr> <tr> <td> <a href="peas.lis_08179aa1bc47182a36430dafec259742.html">peas.lis</a> </td> </tr> </table> </html> """)
def test_01(self): """Test_retHtmlFileName.test_01(): retHtmlFileName() - basic functionality.""" # exp = hashlib.md5(bytes(os.path.abspath(''), 'ascii')).hexdigest() # print(hashlib.md5(bytes(os.path.abspath(''), 'ascii')).hexdigest()) # print(hashlib.md5(bytes(os.path.normpath(''), 'ascii')).hexdigest()) self.assertEqual('_5058f1af8388633f609cadb75a75dc9d.html', HtmlUtils.retHtmlFileName('')) self.assertEqual('foo.lis_7cc7c6edbd4c065f2406358e9211d9eb.html', HtmlUtils.retHtmlFileName('foo.lis')) myPathStr = 'a very long path that goes on and on and on and you think that it will never ever stop spam.lis' myPath = os.path.join(*myPathStr.split()) self.assertEqual( 'a/very/long/path/that/goes/on/and/on/and/on/and/you/think/that/it/will/never/ever/stop/spam.lis', myPath) self.assertEqual( 'spam.lis_899456b1d7f9e35f3f5338b5883ae262.html', HtmlUtils.retHtmlFileName(myPath), )
def test_03(self): """Test_writeFileListAsTable.test_03(): writeFileListAsTable() - Multiple directory list""" myFileNameS = [ 'spam/eggs.lis', 'spam/chips.lis', 'spam/fishfingers/beans.lis', 'spam/fishfingers/peas.lis', ] myFileLinkS = [(f, HtmlUtils.retHtmlFileName(f)) for f in myFileNameS] myF = io.StringIO() with XmlWrite.XhtmlStream(myF) as myS: HtmlUtils.writeFileListAsTable(myS, myFileLinkS, {}, False) # print() # print(myF.getvalue()) # self.maxDiff = None self.assertEqual(myF.getvalue(), """<?xml version='1.0' encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml"> <table> <tr> <td rowspan="4">spam/</td> <td colspan="2"> <a href="chips.lis_78c24a9e68057387b3f7c7de7f57385d.html">chips.lis</a> </td> </tr> <tr> <td colspan="2"> <a href="eggs.lis_afc193e8de9a2e06454b4bf92d5fefd8.html">eggs.lis</a> </td> </tr> <tr> <td rowspan="2">fishfingers/</td> <td> <a href="beans.lis_8c05f2bb7fd4e4946ceae7a0f0a658f1.html">beans.lis</a> </td> </tr> <tr> <td> <a href="peas.lis_93ee5d4c29eb90269e47d1e20daa4110.html">peas.lis</a> </td> </tr> </table> </html> """)
def test_05(self): """TestXhtmlWrite.test_05(): writeHtmlFileAnchor() with class and href.""" myF = io.StringIO() with XmlWrite.XhtmlStream(myF) as myS: HtmlUtils.writeHtmlFileAnchor(myS, 47, theText='Navigation text', theClass='CSS_class', theHref='HREF_TARGET') # print() # print(myF.getvalue()) self.assertEqual(myF.getvalue(), """<?xml version='1.0' encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml"> <a name="47" /> <a href="HREF_TARGET"> <span class="CSS_class">Navigation text</span> </a> </html> """)
def __init__(self, theItu, theHtmlDir, keepGoing=False, macroRefMap=None, cppCondMap=None, ituToTuLineSet=None): """Takes an input source file and an output directory. :param theItu: The original source file path (or file like object for the input). :type theItu: ``str`` :param theHtmlDir: The output directory for the HTML or a file-like object for the output. :type theHtmlDir: ``str`` :param keepGoing: If ``True`` keep going as far as possible. :type keepGoing: ``bool`` :param macroRefMap: Map of ``{identifier : href_text, ...)`` to link to macro definitions. :type macroRefMap: ``dict({str : [list([tuple([<class 'str'>, <class 'int'>, str])]), list([tuple([<class 'str'>, int, str])]), list([tuple([str, int, str])])]})`` :param cppCondMap: Conditional compilation map. :type cppCondMap: :py:class:`cpip.core.CppCond.CppCondGraphVisitorConditionalLines` :param ituToTuLineSet: Set of integer line numbers which are lines that can be linked to the translation unit representation. :type ituToTuLineSet: ``NoneType, set([int])`` :returns: ``NoneType`` """ try: # Assume string or unicode first self._fpIn = theItu self._ituFileObj = open(self._fpIn) except TypeError: self._fpIn = 'Unknown' self._ituFileObj = theItu if isinstance(theHtmlDir, str): if not os.path.exists(theHtmlDir): os.makedirs(theHtmlDir) self._fOut = open( os.path.join(theHtmlDir, HtmlUtils.retHtmlFileName(self._fpIn)), 'w') else: self._fOut = theHtmlDir self._keepGoing = keepGoing # Map of {identifier : href_text, ...) to link to macro definitions. self._macroRefMap = macroRefMap or {} self._cppCondMap = cppCondMap self._ituToTuLineSet = ituToTuLineSet # Start at 0 as this gets incremented before write self._lineNum = 0 self._convert()
def _writeMacroHistory(theS, theMacro, theOmitFiles, theIntOccurence): """Writes out the macro history from a PpDefine object. theMacro - a PpDefine() object. theOmitFiles - a list of pseudo files not to link to e.g. ['Unnamed Pre-include',]. """ anchorName = _retMacroId(theMacro, theIntOccurence) # Write out the macro title with XmlWrite.Element(theS, 'h3'): with XmlWrite.Element(theS, 'a', {'name': anchorName}): theS.characters('%s [References: %d] Defined? %s' \ % ( theMacro.identifier, theMacro.refCount, str(theMacro.isCurrentlyDefined) ) ) with XmlWrite.Element(theS, 'p'): anchorName = _writeMacroDefinitionAndAnchor(theS, theMacro, theIntOccurence) with XmlWrite.Element(theS, 'p'): with XmlWrite.Element(theS, 'tt'): theS.characters('defined @ ') # theS.literal(' ') # theS.characters('@ ') HtmlUtils.writeHtmlFileLink(theS, theMacro.fileId, theMacro.line, '%s#%d' % (theMacro.fileId, theMacro.line), 'file_decl') _writeMacroReferencesTable(theS, theMacro.refFileLineColS) # If inactive then state where #undef'd if not theMacro.isCurrentlyDefined: with XmlWrite.Element(theS, 'p'): with XmlWrite.Element(theS, 'tt'): theS.characters('undef\'d @ ') # theS.literal(' ') # theS.characters('@ ') HtmlUtils.writeHtmlFileLink( theS, theMacro.undefFileId, theMacro.undefLine, '%s#%d' % (theMacro.undefFileId, theMacro.undefLine), 'file_decl')
def test_02(self): """TestXhtmlWrite.test_02(): writeHtmlFileLink() with class.""" myF = io.StringIO() with XmlWrite.XhtmlStream(myF) as myS: HtmlUtils.writeHtmlFileLink(myS, 'spam/eggs/chips.lis', 47, theText='Navigation text', theClass='CSS_class') # print() # print(myF.getvalue()) # self.maxDiff = None self.assertEqual( """<?xml version='1.0' encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml"> <a href="chips.lis_e62fa1654e1857c70203c398c0cbe27d.html#47"> <span class="CSS_class">Navigation text</span> </a> </html> """, myF.getvalue())
def test_02(self): """Test_writeFileListAsTable.test_02(): writeFileListAsTable() - Single directory list""" myFileNameS = [ 'spam/eggs.lis', 'spam/chips.lis', 'spam/beans.lis', ] myFileLinkS = [(f, HtmlUtils.retHtmlFileName(f)) for f in myFileNameS] myF = io.StringIO() with XmlWrite.XhtmlStream(myF) as myS: HtmlUtils.writeFileListAsTable(myS, myFileLinkS, {}, False) # print() # print(myF.getvalue()) # self.maxDiff = None self.assertEqual( myF.getvalue(), """<?xml version='1.0' encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml"> <table> <tr> <td rowspan="3">spam/</td> <td> <a href="beans.lis_85ae02d1d72c7fa819c834e55cd4b1c2.html">beans.lis</a> </td> </tr> <tr> <td> <a href="chips.lis_cf88bd52fd64d0ee6dd7f9f7d465d22b.html">chips.lis</a> </td> </tr> <tr> <td> <a href="eggs.lis_bc8a04943b99ef250322263f7f263272.html">eggs.lis</a> </td> </tr> </table> </html> """)
def _incAndWriteLine(self, theS): self._lineNum += 1 classAttr = 'line' if self._cppCondMap is not None: try: lineIsCompiled = self._cppCondMap.isCompiled(self._fpIn, self._lineNum) except KeyError: pass else: classAttr = self._condCompClassMap[lineIsCompiled] # # Write a link to the TU representation if I am the ITU if self._ituToTuLineSet is not None \ and self._lineNum in self._ituToTuLineSet: myHref = '%s.html#%d' % (os.path.basename(self._fpIn), self._lineNum) else: myHref = None HtmlUtils.writeHtmlFileAnchor( theS, self._lineNum, '%8d:' % self._lineNum, classAttr, theHref=myHref) theS.characters(' ')
def test_01(self): """Test_writeFileListAsTable.test_01(): writeFileListAsTable() - Single file list""" myFileNameS = [ 'eggs.lis', 'chips.lis', 'beans.lis', ] myFileLinkS = [(f, HtmlUtils.retHtmlFileName(f)) for f in myFileNameS] myF = io.StringIO() with XmlWrite.XhtmlStream(myF) as myS: HtmlUtils.writeFileListAsTable(myS, myFileLinkS, {}, False) # print() # print(myF.getvalue()) # self.maxDiff = None self.assertEqual( myF.getvalue(), """<?xml version='1.0' encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml"> <table> <tr> <td> <a href="beans.lis_0041e5194bf9f9efa9f26d5a2139a418.html">beans.lis</a> </td> </tr> <tr> <td> <a href="chips.lis_cb7a31031b69325af0e4d341041c4844.html">chips.lis</a> </td> </tr> <tr> <td> <a href="eggs.lis_66b549ff0dd23f61d7ea822aa9549756.html">eggs.lis</a> </td> </tr> </table> </html> """)
def _incAndWriteLine(self, theS): """Write a line. :param theS: The HTML stream. :type theS: :py:class:`cpip.util.XmlWrite.XhtmlStream` :returns: ``NoneType`` """ self._lineNum += 1 classAttr = 'line' if self._cppCondMap is not None: try: lineIsCompiled = self._cppCondMap.isCompiled( self._fpIn, self._lineNum) except KeyError: logging.error( '_incAndWriteLine(): Ambiguous compilation: path: "{!r:s}" Line: {!r:s}' .format(self._fpIn, self._lineNum)) pass else: classAttr = self._condCompClassMap[lineIsCompiled] # # Write a link to the TU representation if I am the ITU if self._ituToTuLineSet is not None \ and self._lineNum in self._ituToTuLineSet: myHref = '%s.html#%d' % (os.path.basename( self._fpIn), self._lineNum) else: myHref = None HtmlUtils.writeHtmlFileAnchor( theS, # The html stream self._lineNum, # <a name="self._lineNum" '%8d:' % self._lineNum, # Characters to write classAttr, # <span class="classAttr"> to wrap the characters theHref=myHref) # In not None then insert <a href="theHref" theS.characters(' ')
def test_01(self): """Test_writeFileListAsTable.test_01(): writeFileListAsTable() - Single file list""" myFileNameS = [ 'eggs.lis', 'chips.lis', 'beans.lis', ] myFileLinkS = [(f, HtmlUtils.retHtmlFileName(f)) for f in myFileNameS] myF = io.StringIO() with XmlWrite.XhtmlStream(myF) as myS: HtmlUtils.writeFileListAsTable(myS, myFileLinkS, {}, False) # print() # print(myF.getvalue()) # self.maxDiff = None self.assertEqual(myF.getvalue(), """<?xml version='1.0' encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml"> <table> <tr> <td> <a href="beans.lis_37fe59d50e21a22f770f96832a3316be.html">beans.lis</a> </td> </tr> <tr> <td> <a href="chips.lis_52ff1ebbb6b180864516ab041e20da65.html">chips.lis</a> </td> </tr> <tr> <td> <a href="eggs.lis_1355f6695f856c9448c806cfa562a4c4.html">eggs.lis</a> </td> </tr> </table> </html> """)
def writeTuIndexHtml(theOutDir, theTuPath, theLexer, theFileCountMap, theTokenCntr, hasIncDot, macroHistoryIndexName): with XmlWrite.XhtmlStream( os.path.join(theOutDir, tuIndexFileName(theTuPath)), mustIndent=INDENT_ML, ) as myS: with XmlWrite.Element(myS, 'head'): with XmlWrite.Element( myS, 'link', { 'href': TokenCss.TT_CSS_FILE, 'type': "text/css", 'rel': "stylesheet", }): pass with XmlWrite.Element(myS, 'title'): myS.characters('CPIP Processing of %s' % theTuPath) with XmlWrite.Element(myS, 'body'): with XmlWrite.Element(myS, 'h1'): myS.characters('CPIP Processing of %s' % theTuPath) with XmlWrite.Element(myS, 'p'): myS.characters("""This has links to individual pages about the pre-processing of this file.""") # ## # Translation unit # ## with XmlWrite.Element(myS, 'h2'): myS.characters('1. Source Code') _writeParagraphWithBreaks(myS, SOURCE_CODE_INTRO) with XmlWrite.Element(myS, 'h3'): # 'p'): myS.characters('The ') with XmlWrite.Element( myS, 'a', { 'href': HtmlUtils.retHtmlFileName(theTuPath), }): myS.characters('source file') myS.characters(' and ') with XmlWrite.Element(myS, 'a', { 'href': tuFileName(theTuPath), }): myS.characters('as a translation unit') # ## # Include graph # ## with XmlWrite.Element(myS, 'h2'): myS.characters('2. Include Graphs') _writeParagraphWithBreaks(myS, INCLUDE_GRAPH_INTRO) with XmlWrite.Element(myS, 'h3'): # 'p'): myS.characters('A ') with XmlWrite.Element( myS, 'a', { 'href': includeGraphFileNameSVG(theTuPath), }): myS.characters('visual #include tree in SVG') # If we have successfully written a .dot file then link to it if hasIncDot: myS.characters(', ') with XmlWrite.Element( myS, 'a', { 'href': includeGraphFileNameDotSVG(theTuPath), }): myS.characters('Dot dependency [SVG]') myS.characters(' or ') with XmlWrite.Element( myS, 'a', { 'href': includeGraphFileNameText(theTuPath), }): myS.characters('as Text') # ## # Conditional compilation # ## with XmlWrite.Element(myS, 'h2'): myS.characters('3. Conditional Compilation') _writeParagraphWithBreaks(myS, CONDITIONAL_COMPILATION_INTRO) with XmlWrite.Element(myS, 'h3'): # 'p'): myS.characters('The ') with XmlWrite.Element( myS, 'a', { 'href': includeGraphFileNameCcg(theTuPath), }): myS.characters('conditional compilation graph') # ## # Macro history # ## with XmlWrite.Element(myS, 'h2'): myS.characters('4. Macros') _writeParagraphWithBreaks(myS, MACROS_INTRO) with XmlWrite.Element(myS, 'h3'): myS.characters('The ') with XmlWrite.Element(myS, 'a', { 'href': macroHistoryIndexName, }): myS.characters('Macro Environment') # ## # Write out token counter as a table # ## with XmlWrite.Element(myS, 'h2'): myS.characters('5. Token Count') _writeParagraphWithBreaks(myS, TOKEN_COUNT_INTRO) with XmlWrite.Element(myS, 'table', {'class': "monospace"}): with XmlWrite.Element(myS, 'tr'): with XmlWrite.Element(myS, 'th', {'class': "monospace"}): myS.characters('Token Type') with XmlWrite.Element(myS, 'th', {'class': "monospace"}): myS.characters('Count') myTotal = 0 for tokType, tokCount in theTokenCntr.tokenTypesAndCounts( isAll=True, allPossibleTypes=True): with XmlWrite.Element(myS, 'tr'): with XmlWrite.Element(myS, 'td', {'class': "monospace"}): myS.characters(tokType) with XmlWrite.Element(myS, 'td', {'class': "monospace"}): # <tt> does not preserve space so force it to myStr = '%10d' % tokCount myStr = myStr.replace(' ', ' ') myS.literal(myStr) myTotal += tokCount with XmlWrite.Element(myS, 'tr'): with XmlWrite.Element(myS, 'td', {'class': "monospace"}): with XmlWrite.Element(myS, 'b'): myS.characters('Total:') with XmlWrite.Element(myS, 'td', {'class': "monospace"}): with XmlWrite.Element(myS, 'b'): # <tt> does not preserve space so force it to myStr = '%10d' % myTotal myStr = myStr.replace(' ', ' ') myS.literal(myStr) with XmlWrite.Element(myS, 'br'): pass with XmlWrite.Element(myS, 'h2'): myS.characters('6. Files Included and Count') _writeParagraphWithBreaks(myS, FILES_INCLUDED_INTRO) with XmlWrite.Element(myS, 'p'): myS.characters('Total number of unique files: %d' % len(theFileCountMap)) # TODO: Value count # with XmlWrite.Element(myS, 'p'): # myS.characters('Total files processed: %d' % sum(theFileCountMap.values())) myItuFileS = sorted(theFileCountMap.keys()) # Create a list for the DictTree myFileLinkS = [ ( p, # Value is a tripple (href, basename, count) (HtmlUtils.retHtmlFileName(p), os.path.basename(p), theFileCountMap[p]), ) for p in myItuFileS if p != PpLexer.UNNAMED_FILE_NAME ] HtmlUtils.writeFilePathsAsTable(None, myS, myFileLinkS, 'filetable', _tdCallback) with XmlWrite.Element(myS, 'br'): pass # TODO... with XmlWrite.Element(myS, 'p'): myS.characters('Produced by %s version: %s' % ('CPIPMain', __version__)) # Back link with XmlWrite.Element(myS, 'p'): myS.characters('Back to: ') with XmlWrite.Element(myS, 'a', { 'href': 'index.html', }): myS.characters('Index Page')
def processTuToHtml(theLex, theHtmlPath, theTitle, theCondLevel, theIdxPath, incItuAnchors=True): """Processes the PpLexer and writes the tokens to the HTML file. *theHtmlPath* The path to the HTML file to write. *theTitle* A string to go into the <title> element. *theCondLevel* The Conditional level to pass to theLex.ppTokens() *theIdxPath* Path to link back to the index page. *incItuAnchors* boolean, if True will write anchors for lines in the ITU that are in this TU. If True then setItuLineNumbers returned is likely to be non-empty. Returns a pair of (PpTokenCount.PpTokenCount(), set(int)) The latter is a set of integer line numbers in the ITU that are in the TU, these line numbers with have anchors in this HTML file of the form: <a name="%d" />.""" if not os.path.exists(os.path.dirname(theHtmlPath)): os.makedirs(os.path.dirname(theHtmlPath)) LINE_FIELD_WIDTH = 8 LINE_BREAK_LENGTH = 100 # Make a global token counter (this could be got from the file include graph # but this is simpler. myTokCntr = PpTokenCount.PpTokenCount() # Write CSS TokenCss.writeCssToDir(os.path.dirname(theHtmlPath)) # Set of active lines of the ITU (only) that made it into the TU setItuLineNumbers = set() # Process the TU with XmlWrite.XhtmlStream(theHtmlPath, mustIndent=cpip.INDENT_ML) as myS: with XmlWrite.Element(myS, 'head'): with XmlWrite.Element( myS, 'link', { 'href' : TokenCss.TT_CSS_FILE, 'type' : "text/css", 'rel' : "stylesheet", } ): pass with XmlWrite.Element(myS, 'title'): myS.characters(theTitle) myIntId = 0 with XmlWrite.Element(myS, 'body'): with XmlWrite.Element(myS, 'h1'): myS.characters('Translation Unit: %s' % theLex.tuFileId) with XmlWrite.Element(myS, 'p'): myS.characters("""An annotated version of the translation unit with minimal whitespace. Indentation is according to the depth of the #include stack. Line numbers are linked to the original source code. """) with XmlWrite.Element(myS, 'p'): myS.characters("""Highlighted filenames take you forward to the next occasion in the include graph of the file being pre-processed, in this case: %s""" % theLex.tuFileId) linkToIndex(myS, theIdxPath) with XmlWrite.Element(myS, 'pre'): # My copy of the file stack for annotating the output myFileStack = [] indentStr = '' colNum = 1 for t in theLex.ppTokens(incWs=True, minWs=True, condLevel=theCondLevel): #print t logging.debug('Token: %s', str(t)) myTokCntr.inc(t, isUnCond=t.isUnCond, num=1) if t.isUnCond: # Adjust the prefix depending on how deep we are in the file stack myIntId = _adjustFileStack(myS, theLex.fileStack, myFileStack, myIntId) indentStr = '.' * len(myFileStack) # Write the token if t.tt == 'whitespace': if t.t != '\n' and colNum > LINE_BREAK_LENGTH: myS.characters(' \\\n') myS.characters(indentStr) myS.characters(' ' * (LINE_FIELD_WIDTH + 8)) colNum = 1 else: # Line break myS.characters(t.t) ## NOTE: This is removed as the cost to the ## browser is enormous. ## Set a marker #with XmlWrite.Element(myS, # 'a', # {'name' : myTuI.add(theLex.tuIndex)}): # pass else: if colNum > LINE_BREAK_LENGTH: # Force a break myS.characters('\\\n') myS.characters(indentStr) myS.characters(' ' * (LINE_FIELD_WIDTH + 8)) colNum = 1 with XmlWrite.Element(myS, 'span', {'class' : TokenCss.retClass(t.tt)}): myS.characters(t.t) colNum += len(t.t) if t.t == '\n' and len(myFileStack) != 0: # Write an ID for the ITU only if incItuAnchors and len(myFileStack) == 1: with XmlWrite.Element(myS, 'a', {'name' : '%d' % theLex.lineNum}): setItuLineNumbers.add(theLex.lineNum) # Write the line prefix myS.characters(indentStr) myS.characters('[') myS.characters(' ' * \ (LINE_FIELD_WIDTH - len('%d' % theLex.lineNum))) HtmlUtils.writeHtmlFileLink( myS, theLex.fileName, theLex.lineNum, '%d' % theLex.lineNum, theClass=None, ) myS.characters(']: ') colNum = 1 linkToIndex(myS, theIdxPath) return myTokCntr, setItuLineNumbers
def tuIndexFileName(theTu): return 'index_' + HtmlUtils.retHtmlFileName(theTu)