Passing an error reoter hook into WmlIterator was dumb.

This sort of thing is what subclassing is for.
This commit is contained in:
Eric S. Raymond 2008-11-06 23:45:59 +00:00
parent 7800a69318
commit 90e8b6e052
2 changed files with 26 additions and 20 deletions

View file

@ -74,6 +74,11 @@ class WmlIterator(object):
Initialize with a list of lines or a file; if the the line list is
empty and the filename is specified, lines will be read from the file.
This is meant to be subclassed. It needs a printError method but
does not have one. The method should take any number of string arguments,
compose them into an error notification, and deliver it. It may fire
more than once during the instance lifetime.
Note: if changes are made to lines while iterating, this may produce
unexpected results. In such case, seek() to the linenumber of a
scope behind where changes were made.
@ -92,7 +97,7 @@ Important Attributes:
always 1, unless text contains a multi-line quoted string
lineno - a zero-based line index marking where this text begins
"""
def __init__(self, lines=None, filename=None, begin=-1, onerr=None):
def __init__(self, lines=None, filename=None, begin=-1):
"Initialize a new WmlIterator."
self.fname = filename
if lines is None:
@ -103,9 +108,8 @@ Important Attributes:
lines = ifp.readlines()
ifp.close()
except Exception:
self.onerr(self, 'error opening file')
self.printError('error opening file')
self.lines = lines
self.onerr = onerr
self.reset()
self.seek(begin)
@ -124,7 +128,7 @@ Important Attributes:
endquote = text.find('"', beginofend)
if endquote < 0:
if self.lineno + span >= len(lines):
self.onerr(self, 'reached EOF due to unterminated string')
self.printError('reached EOF due to unterminated string')
return text, span
text += lines[self.lineno + span]
span += 1
@ -151,7 +155,7 @@ Important Attributes:
if ((isOpener(elem) and closerElement != '[/'+elem[1:]
and '+'+closerElement != elem[1]+'[/'+elem[2:])
or (elem.startswith('{') and closerElement.find('macro')<0)):
self.onerr(self, 'reached', closerElement, 'before closing scope', elem)
self.printError('reached', closerElement, 'before closing scope', elem)
scopes.append(closed) # to reduce additional errors (hopefully)
return True
except IndexError:
@ -247,7 +251,7 @@ Important Attributes:
def printScopeError(self, elementType):
"""Print out warning if a scope was unable to close"""
self.onerr(self, 'attempt to close empty scope at', elementType)
self.printError('attempt to close empty scope at', elementType)
def __iter__(self):
"""The magic iterator method"""
@ -324,7 +328,7 @@ Important Attributes:
note: May raise StopIteration"""
if not self.hasNext():
if self.scopes:
self.onerr(self, "reached EOF with open scopes", self.scopes)
self.printError("reached EOF with open scopes", self.scopes)
raise StopIteration
self.lineno = self.lineno + self.span
self.text, self.span = self.parseQuotes(self.lines)

View file

@ -333,19 +333,21 @@ declared_spellings = {"GLOBAL":["I'm", "I've", "I'd", "I'll",
"princeling", "wilderlands", "ensorcels"
]}
def printError(nav, *misc):
"""Emit an error locator compatible with Emacs compilation mode."""
if nav.lineno == -1:
print >>sys.stderr, '"%s":' % nav.fname
else:
print >>sys.stderr, '"%s", line %d:' % (nav.fname, nav.lineno+1)
for item in misc:
print >>sys.stderr, item,
print >>sys.stderr #terminate line
class WmllintIterator(WmlIterator):
"Fold an Emacs-compatible error reporter into WmlIterator."
def printError(self, *misc):
"""Emit an error locator compatible with Emacs compilation mode."""
if self.lineno == -1:
print >>sys.stderr, '"%s":' % self.fname
else:
print >>sys.stderr, '"%s", line %d:' % (self.fname, self.lineno+1)
for item in misc:
print >>sys.stderr, item,
print >>sys.stderr #terminate line
def sanity_check(filename, lines):
"Perform sanity and consistency checks on input lines."
for nav in WmlIterator(filename=fn, onerr=printError):
for nav in WmllintIterator(filename=fn):
# Check for things marked translated that aren't strings
if "_" in nav.text and not "wmllint: ignore" in nav.text:
m = re.search(r'[=(]\s*_\s+("?)', nav.text)
@ -1198,7 +1200,7 @@ def spellcheck(fn, d):
map(d.add_to_session, local_spellings)
# Process this individual file
for nav in WmlIterator(filename=fn, onerr=printError):
for nav in WmllintIterator(filename=fn):
#print "element=%s, text=%s" % (nav.element, `nav.text`)
# Recognize local spelling exceptions
if not nav.element and "#" in nav.text:
@ -1211,11 +1213,11 @@ def spellcheck(fn, d):
d.add_to_session(word)
local_spellings.append(word)
else:
printError(nav, " %s already declared" % word)
nav.printError(" %s already declared" % word)
#if local_spellings:
# print "%s: with this file's local spellings: %s" % (fn,local_spellings)
for nav in WmlIterator(filename=fn, onerr=printError):
for nav in WmllintIterator(filename=fn):
# Spell-check message and story parts
if nav.element in spellcheck_these:
# Special case, beyond us until we can do better filtering..