Statistics on body.py --------------------- Solo verified by Shipman using trace tables: see body.vrf for the trace tables themselves. Program size: 253/1305 code lines, 19% non-blank non-comment lines. ================================================================ Syntax errors ---------------------------------------------------------------- S1 ================================================================ Bugs that would be caught in a more strongly-typed language ---------------------------------------------------------------- T1 In Body.__findSiblings(), this line parent = topic.parent should be: parent = self.topic.parent ---------------------------------------------------------------- T2 Must import log.py and scan.py modules ---------------------------------------------------------------- T3 In Body.__makeLink(), this code: self.append ( '%s' % ( path, linkText ) ) should be: self.text.append ( '%s' % ( path, linkText ) ) ---------------------------------------------------------------- T4 Body.__parseRRTag() refers to the LinkVar() constructor, but that class is in `plan'. The class was moved here to avoid a reference loop, since plan imports body.py. For all I know Python can actually handle import loops, but since the constructor is called only from here, class LinkVar really does belong in body.py. ---------------------------------------------------------------- T5 There are several references to the Target() constructor in body.py, and also in plan.py. Since plan imports body, the Target class has been moved here. ---------------------------------------------------------------- ================================================================ Logic bugs ---------------------------------------------------------------- B1 In Body.__parseUpdatedTag(), if the call to scan.reMatch() failed, the error message was written, but then control fell through to the success case. Needs a `return'. ---------------------------------------------------------------- B2 In Body.__parseUpdatedTag(), this line: m = scan.reMatch ( self.datePat ) assumes that the pattern is still in the scan stream, but it has already been digested. The code should be: m = self.datePat.match ( tagAttr.value ) ---------------------------------------------------------------- B3 In Body.__parseUpdatedTag(), this condition: if ( ( len ( timestamp ) < 2 ) or ( timestamp[0] != ": " ) ): should be: if ( ( len ( timestamp ) < 2 ) or ( timestamp[0:2] != ": " ) ): ---------------------------------------------------------------- B4 In Body.__init__(), self.author and self.updated should be initialized to None. ---------------------------------------------------------------- B5 In Body.__readNonTag(), the logic to check whether there is a "<" on the current line used to look like this: tagStart = scan.find ( "<" ) if tagStart: but that does not work for the case where the "<" is the first thing on the line---in that case, scan.find() returns 0, which is a valid position, but treated as false! So the test must be: if tagStart is not None: ---------------------------------------------------------------- B6 In Body.__read(), no message is given if the .g file does not exist. The fault is that Body.__read() seems to assume that Scan() sends a message to Log() if it can't open, but the scan module was changed some time ago (years!) so that it does not emit message---in case the caller wants to probe for the existence of a file by trying to open it. So, the fix is to replace: scan = Scan ( fileName ) with: try: scan = Scan ( fileName ) except IOError, detail: Log().error ( "Can't open input file `%s'" % fileName ) raise IOError, detail ----------------------------------------------------------------