Skip to content
Fetching contributors…
Cannot retrieve contributors at this time
executable file 204 lines (167 sloc) 6.14 KB
''' atdtool
Command-line client for After the Deadline:
Based on AtD module by Miguel Ventura:
from optparse import OptionParser
import re
import sys
import httplib
import urllib
from xml.etree import ElementTree
PROGRAM_NAME = "atdtool"
def checkDocument(cfg, fd):
'''Invoke checkDocument service and return a list of errors.'''
server = cfg.server
if cfg.lang != '':
server = cfg.lang + '.' + cfg.server
service = httplib.HTTPConnection(server)
service.request('POST', '/checkDocument', urllib.urlencode({ 'key': cfg.key, 'data': }))
response = service.getresponse()
if response.status != httplib.OK:
raise Exception('Unexpected response code from AtD server %s: %d' % (cfg.server, response.status))
et = ElementTree.fromstring(
errs = et.findall('message')
if len(errs) > 0:
raise Exception('Server returned an error: %s' % errs[0].text)
return [ Error(e) for e in et.findall('error') ]
class Error:
'''Error objects.'''
def __init__(self, e):
self.string = e.find('string').text
self.description = e.find('description').text
self.precontext = e.find('precontext').text
self.type = e.find('type').text
self.url = ''
if not e.find('url') is None:
self.url = e.find('url').text
self.suggestions = []
if not e.find('suggestions') is None:
self.suggestions = [ o.text for o in e.find('suggestions').findall('option') ]
class FileWords:
'''Parser class, keeps line and column position.'''
def __init__(self, fd): = re.compile('([^a-z0-9A-Z_-])')
self.skipre = re.compile('[^a-z0-9A-Z_-]+')
self.text =
self.len = len(self.text)
def reset(self):
'''Goes to start of file.'''
self.i = 0
self.line = 1
self.col = 0
self.eof = False
def next(self):
'''Goes to next token.'''
if self.eof:
self.col = self.col + len(self.text[self.i])
self.i = self.i + 1
if self.i >= self.len:
self.eof = True
if self.text[self.i] == '\n':
self.line = self.line + 1
self.col = 0
def skipnw(self):
'''Skips non-word tokens.'''
while self.skipre.match(self.text[self.i]) or self.text[self.i] == '':
def checkpos(self, words0):
'''Checks if words0 is in current position.'''
words = tuple(
text = self.text
t = []
j = 0
w = ''
while len(t) < len(words):
if self.i + j == self.len:
self.eof = True
return False, ''
w = w + text[self.i+j]
if self.i + j + 1 < self.len and text[self.i+j+1] == '.':
t.append(t.pop() + text[self.i+j+2])
w = w + '.' + text[self.i+j+2]
j = j + 1
return tuple(t) == words, w
def goto(self, prec, words):
'''Goes to words preceded by prec; returns False and stays at eof if not found.'''
found = False
w = ''
if prec:
target = prec
target = words
while not self.eof and not found:
found, w = self.checkpos(target)
if not found:
elif prec:
found, w = self.checkpos(words)
if found:
self.words = w
return True
return False
def find(self, prec, words):
'''Tries to find words preceded by prec from current position, then from start of file.'''
found = self.goto(prec, words)
if not found:
found = self.goto(prec, words)
return found
def showerrs(filename, fd, errs):
'''Shows the errors found, in the context of the file.'''
t = FileWords(fd)
for e in errs:
exactstr = ''
if not t.find(e.precontext, e.string):
exactstr = ' (?)'
print('%s:%d:%d:%s %s "%s"' % (filename, t.line, t.col, exactstr, e.description, t.words))
if len(e.suggestions) > 0:
print(' suggestions: %s' % ', '.join(e.suggestions))
def main():
parser = OptionParser(usage='Usage: %prog <file>',
version="%prog "+PROGRAM_VERSION,
atdtool submits the given file to the After the Deadline language checking
service at and presents the results in
the same format as gcc, making integration with other tools (vi, emacs, etc.)
parser.add_option('-s', '--server', dest='server', help='Select AtD server', default='')
parser.add_option('-l', '--language', dest='lang', help='Select language server [fr/de/pt/es]', default='')
parser.add_option('-e', '--error', dest='error', help='Exit with error if any mistakes are found', default=False)
parser.add_option('-k', '--key', dest='key', help='Key to use', default='')
(cfg, args) = parser.parse_args()
if len(args) == 0:
parser.error('expecting file argument')
if cfg.server != '' and cfg.lang != '':
parser.error('The language selects an official AtD server, there is no reason to specify both.')
founderr = False
for filename in args:
fd = None
fd = open(filename)
except IOError:
print('%s: No such file or directory' % filename)
if not fd:
errs = checkDocument(cfg, fd)
founderr = founderr or len(errs) > 0
showerrs(filename, fd, errs)
if cfg.error and founderr:
if __name__ == '__main__':
Something went wrong with that request. Please try again.