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
----------------------------------------------------------------