Mercurial > hgbook
diff ja/examples/run-example @ 776:019040fbf5f5
merged to upstream: phase 1
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Tue, 21 Apr 2009 00:36:40 +0900 |
parents | en/examples/run-example@3b640272a966 en/examples/run-example@32d33b238b7e |
children |
line wrap: on
line diff
--- a/ja/examples/run-example Mon Apr 20 23:50:34 2009 +0900 +++ b/ja/examples/run-example Tue Apr 21 00:36:40 2009 +0900 @@ -7,6 +7,7 @@ import cStringIO import errno import getopt +import glob import os import pty import re @@ -18,23 +19,23 @@ import tempfile import time -tex_subs = { - '\\': '\\textbackslash{}', - '{': '\\{', - '}': '\\}', +xml_subs = { + '<': '<', + '>': '>', + '&': '&', } def gensubs(s): start = 0 for i, c in enumerate(s): - sub = tex_subs.get(c) + sub = xml_subs.get(c) if sub: yield s[start:i] start = i + 1 yield sub yield s[start:] -def tex_escape(s): +def xml_escape(s): return ''.join(gensubs(s)) def maybe_unlink(name): @@ -53,7 +54,92 @@ return p return None +def result_name(name): + return os.path.normpath(os.path.join('results', name.replace(os.sep, '-'))) + +def wopen(name): + path = os.path.dirname(name) + if path: + try: + os.makedirs(path) + except OSError, err: + if err.errno != errno.EEXIST: + raise + return open(name, 'w') + class example: + entities = dict.fromkeys(l.rstrip() for l in open('auto-snippets.xml')) + + def __init__(self, name, verbose, keep_change): + self.name = os.path.normpath(name) + self.verbose = verbose + self.keep_change = keep_change + + def status(self, s): + sys.stdout.write(s) + if not s.endswith('\n'): + sys.stdout.flush() + + def rename_output(self, base, ignore=[]): + mangle_re = re.compile('(?:' + '|'.join(ignore) + ')') + def mangle(s): + return mangle_re.sub('', s) + def matchfp(fp1, fp2): + while True: + s1 = mangle(fp1.readline()) + s2 = mangle(fp2.readline()) + if cmp(s1, s2): + break + if not s1: + return True + return False + + oldname = result_name(base + '.out') + tmpname = result_name(base + '.tmp') + errname = result_name(base + '.err') + errfp = open(errname, 'w+') + for line in open(tmpname): + errfp.write(mangle_re.sub('', line)) + os.rename(tmpname, result_name(base + '.lxo')) + errfp.seek(0) + try: + oldfp = open(oldname) + except IOError, err: + if err.errno != errno.ENOENT: + raise + os.rename(errname, oldname) + return False + if matchfp(oldfp, errfp): + os.unlink(errname) + return False + else: + print >> sys.stderr, '\nOutput of %s has changed!' % base + if self.keep_change: + os.rename(errname, oldname) + return False + else: + os.system('diff -u %s %s 1>&2' % (oldname, errname)) + return True + +class static_example(example): + def run(self): + self.status('running %s\n' % self.name) + s = open(self.name).read().rstrip() + s = s.replace('&', '&').replace('<', '<').replace('>', '>') + ofp = wopen(result_name(self.name + '.tmp')) + ofp.write('<!-- BEGIN %s -->\n' % self.name) + ofp.write('<programlisting>') + ofp.write(s) + ofp.write('</programlisting>\n') + ofp.write('<!-- END %s -->\n' % self.name) + ofp.close() + self.rename_output(self.name) + norm = self.name.replace(os.sep, '-') + example.entities[ + '<!ENTITY %s SYSTEM "results/%s.lxo">' % (norm, norm)] = 1 + + +class shell_example(example): shell = '/usr/bin/env bash' ps1 = '__run_example_ps1__ ' ps2 = '__run_example_ps2__ ' @@ -61,9 +147,8 @@ timeout = 10 - def __init__(self, name, verbose): - self.name = name - self.verbose = verbose + def __init__(self, name, verbose, keep_change): + example.__init__(self, name, verbose, keep_change) self.poll = select.poll() def parse(self): @@ -76,11 +161,6 @@ yield cfp.getvalue() cfp.seek(0) cfp.truncate() - - def status(self, s): - sys.stdout.write(s) - if not s.endswith('\n'): - sys.stdout.flush() def send(self, s): if self.verbose: @@ -146,12 +226,12 @@ maybe_unlink(self.name + '.run') rcfile = os.path.join(tmpdir, '.hgrc') - rcfp = open(rcfile, 'w') + rcfp = wopen(rcfile) print >> rcfp, '[ui]' print >> rcfp, "username = Bryan O'Sullivan <bos@serpentine.com>" rcfile = os.path.join(tmpdir, '.bashrc') - rcfp = open(rcfile, 'w') + rcfp = wopen(rcfile) print >> rcfp, 'PS1="%s"' % self.ps1 print >> rcfp, 'PS2="%s"' % self.ps2 print >> rcfp, 'unset HISTFILE' @@ -230,12 +310,22 @@ return 1 assert os.sep not in out if ofp is not None: + ofp.write('</screen>\n') + ofp.write('<!-- END %s -->\n' % ofp_basename) ofp.close() err |= self.rename_output(ofp_basename, ignore) if out: ofp_basename = '%s.%s' % (self.name, out) + norm = os.path.normpath(ofp_basename) + norm = norm.replace(os.sep, '-') + example.entities[ + '<!ENTITY interaction.%s ' + 'SYSTEM "results/%s.lxo">' + % (norm, norm)] = 1 read_hint = ofp_basename + ' ' - ofp = open(ofp_basename + '.tmp', 'w') + ofp = wopen(result_name(ofp_basename + '.tmp')) + ofp.write('<!-- BEGIN %s -->\n' % ofp_basename) + ofp.write('<screen>') else: ofp = None elif pi == 'ignore': @@ -248,14 +338,15 @@ # first, print the command we ran if not hunk.startswith('#'): nl = hunk.endswith('\n') - hunk = ('%s \\textbf{%s}' % + hunk = ('<prompt>%s</prompt> ' + '<userinput>%s</userinput>' % (prompts[ps], - tex_escape(hunk.rstrip('\n')))) + xml_escape(hunk.rstrip('\n')))) if nl: hunk += '\n' ofp.write(hunk) # then its output - ofp.write(tex_escape(output)) - ps = newps + ofp.write(xml_escape(output)) + ps = newps self.status('\n') except: print >> sys.stderr, '(killed)' @@ -267,6 +358,8 @@ ps, output = self.sendreceive('exit\n', read_hint) if ofp is not None: ofp.write(output) + ofp.write('</screen>\n') + ofp.write('<!-- END %s -->\n' % ofp_basename) ofp.close() err |= self.rename_output(ofp_basename, ignore) os.close(self.cfd) @@ -281,69 +374,40 @@ elif os.WIFSIGNALED(rc): print >> sys.stderr, '(signal %s)' % os.WTERMSIG(rc) else: - open(self.name + '.run', 'w') -# return err - return 0 + wopen(result_name(self.name + '.run')) + return err finally: shutil.rmtree(tmpdir) - def rename_output(self, base, ignore): - mangle_re = re.compile('(?:' + '|'.join(ignore) + ')') - def mangle(s): - return mangle_re.sub('', s) - def matchfp(fp1, fp2): - while True: - s1 = mangle(fp1.readline()) - s2 = mangle(fp2.readline()) - if cmp(s1, s2): - break - if not s1: - return True - return False - - oldname = base + '.out' - tmpname = base + '.tmp' - errname = base + '.err' - errfp = open(errname, 'w+') - for line in open(tmpname): - errfp.write(mangle_re.sub('', line)) - os.rename(tmpname, base + '.lxo') - errfp.seek(0) - try: - oldfp = open(oldname) - except IOError, err: - if err.errno != errno.ENOENT: - raise - os.rename(errname, oldname) - return False - if matchfp(oldfp, errfp): - os.unlink(errname) - return False - else: - print >> sys.stderr, '\nOutput of %s has changed!' % base - os.system('diff -u %s %s 1>&2' % (oldname, errname)) - return True - def print_help(exit, msg=None): if msg: print >> sys.stderr, 'Error:', msg print >> sys.stderr, 'Usage: run-example [options] [test...]' print >> sys.stderr, 'Options:' - print >> sys.stderr, ' -a --all run all tests in this directory' + print >> sys.stderr, ' -a --all run all examples in this directory' print >> sys.stderr, ' -h --help print this help message' + print >> sys.stderr, ' --keep keep new output as desired output' print >> sys.stderr, ' -v --verbose display extra debug output' sys.exit(exit) def main(path='.'): + if os.path.realpath(path).split(os.sep)[-1] != 'examples': + print >> sys.stderr, 'Not being run from the examples directory!' + sys.exit(1) + opts, args = getopt.getopt(sys.argv[1:], '?ahv', - ['all', 'help', 'verbose']) + ['all', 'help', 'keep', 'verbose']) verbose = False run_all = False + keep_change = False + for o, a in opts: if o in ('-h', '-?', '--help'): print_help(0) if o in ('-a', '--all'): run_all = True + if o in ('--keep',): + keep_change = True if o in ('-v', '--verbose'): verbose = True errs = 0 @@ -355,19 +419,20 @@ print >> sys.stderr, '%s: %s' % (a, err.strerror) errs += 1 continue - if stat.S_ISREG(st.st_mode) and st.st_mode & 0111: - if example(a, verbose).run(): - errs += 1 + if stat.S_ISREG(st.st_mode): + if st.st_mode & 0111: + if shell_example(a, verbose, keep_change).run(): + errs += 1 + elif a.endswith('.lst'): + static_example(a, verbose, keep_change).run() else: print >> sys.stderr, '%s: not a file, or not executable' % a errs += 1 elif run_all: - names = os.listdir(path) + names = glob.glob("*") + glob.glob("app*/*") + glob.glob("ch*/*") names.sort() for name in names: - if name == 'run-example' or name.startswith('.'): continue - if name.endswith('.out') or name.endswith('~'): continue - if name.endswith('.run'): continue + if name == 'run-example' or name.endswith('~'): continue pathname = os.path.join(path, name) try: st = os.lstat(pathname) @@ -376,12 +441,20 @@ if err.errno != errno.ENOENT: raise continue - if stat.S_ISREG(st.st_mode) and st.st_mode & 0111: - if example(pathname, verbose).run(): - errs += 1 - print >> open(os.path.join(path, '.run'), 'w'), time.asctime() + if stat.S_ISREG(st.st_mode): + if st.st_mode & 0111: + if shell_example(pathname, verbose, keep_change).run(): + errs += 1 + elif pathname.endswith('.lst'): + static_example(pathname, verbose, keep_change).run() + print >> wopen(os.path.join(path, '.run')), time.asctime() else: print_help(1, msg='no test names given, and --all not provided') + + fp = wopen('auto-snippets.xml') + for key in sorted(example.entities.iterkeys()): + print >> fp, key + fp.close() return errs if __name__ == '__main__':