Statistics on template.py ------------------------- Solo verified by Shipman using trace tables: see template.vrf for the trace tables themselves. Program size: 276/1255 code lines, 22% non-blank non-comment lines. ================================================================ Syntax errors ---------------------------------------------------------------- S1 In Template.__readFormat(): scan.error ( "There is no such format code as `%s%s%s'." % START_FORMAT, gi, END_FORMAT ) should be: scan.error ( "There is no such format code as `%s%s%s'." % ( START_FORMAT, gi, END_FORMAT ) ) ---------------------------------------------------------------- ================================================================ Bugs that would be caught in a more strongly-typed language ---------------------------------------------------------------- T1 In Template.__readFile(): while not scan.endFile: should be: while not scan.atEndFile: ---------------------------------------------------------------- T2 In Template.__readFormat(): gi = scan.tabMany ( string.lower ( FORMAT_NAME_CSET ) ) should be: gi = string.lower ( scan.tabMany ( FORMAT_NAME_CSET ) ) ---------------------------------------------------------------- T3 In Template.__readFormat(), the call to LiteralToken() was missing the `openCondStack' and `scan' arguments. ---------------------------------------------------------------- T4 Forgot to write Template.expand(). Fortunately, it's pretty short. ---------------------------------------------------------------- T5 The line `class Condition:' was not flush left---it was indented four, so it was considered part of the previous class. This created a number of weird effects that were hard to find. ---------------------------------------------------------------- T6 In IfStack.end(), this line: del __stack[-1] should be: del self.__stack[-1] ---------------------------------------------------------------- T7 In UpURLToken.expand(), in this call to TToken.writeLink(): self.writeLink ( outFile, body.topic, body.topic.parent ) the third argument should be a Target for the body's topic's parent, not just the body's topic's parent: self.writeLink ( outFile, body.topic, Target ( body.topic.parent, None ) ) This patch necessitated inclusion of the body.py module in this module so we could access the Target() constructor. ---------------------------------------------------------------- T8 In Template.__readToken(), this error message call: if len ( self.__openCondStack ) > 0: for openCond in self.__openCondStack: scan.error ( "A conditional `%%%s;' construct that " "starts on line %d is unclosed.", <-- Not a comma! ( openCond.name, openCond.lineNo ) ) should be: if len ( self.__openCondStack ) > 0: for openCond in self.__openCondStack: scan.error ( "A conditional `%%%s;' construct that " "starts on line %d is unclosed." % <-- Format operator ( openCond.name, openCond.lineNo ) ) ---------------------------------------------------------------- ================================================================ Logic bugs ---------------------------------------------------------------- B1 Made a subtle but dire mistake in the singleton wrapper for TmplPool(). This line: _TmplPool.instance = TmplPool() causes a very hard recursion loop, and should be: _TmplPool.instance = _TmplPool() ---------------------------------------------------------------- B2 In the Template.formatScanners dispatch table, the key for "see" should be "seealso". ---------------------------------------------------------------- B3 In TmplPool.__init__(), there was no check to see if the defTemplate argument should be replaced by DEFAULT_TEMPLATE if it was passed in as None. ---------------------------------------------------------------- B4 I had two copies of TToken.writeLink(). The second one should have been .writeStdLink()---the perils of cut and paste! Especially because the second one called .writeLink(), which led to a pretty tight loop. ---------------------------------------------------------------- B5 In Template.__readFormat, look at these last four lines in the formatScanners table: "updated": URLToken, "uptitle": UpTitleToken, "upurl": UpURLToken, "url": UpdateToken } the right-hand sides of the first and fourth are backwards. ---------------------------------------------------------------- B6 IfUpToken.expand() has the sense of its test backwards. ----------------------------------------------------------------