summaryrefslogtreecommitdiffstats
path: root/AppPkg/Applications/Python/Python-2.7.2/Tools/faqwiz/faqwiz.py
diff options
context:
space:
mode:
Diffstat (limited to 'AppPkg/Applications/Python/Python-2.7.2/Tools/faqwiz/faqwiz.py')
-rw-r--r--AppPkg/Applications/Python/Python-2.7.2/Tools/faqwiz/faqwiz.py841
1 files changed, 841 insertions, 0 deletions
diff --git a/AppPkg/Applications/Python/Python-2.7.2/Tools/faqwiz/faqwiz.py b/AppPkg/Applications/Python/Python-2.7.2/Tools/faqwiz/faqwiz.py
new file mode 100644
index 0000000000..babb426582
--- /dev/null
+++ b/AppPkg/Applications/Python/Python-2.7.2/Tools/faqwiz/faqwiz.py
@@ -0,0 +1,841 @@
+"""Generic FAQ Wizard.
+
+This is a CGI program that maintains a user-editable FAQ. It uses RCS
+to keep track of changes to individual FAQ entries. It is fully
+configurable; everything you might want to change when using this
+program to maintain some other FAQ than the Python FAQ is contained in
+the configuration module, faqconf.py.
+
+Note that this is not an executable script; it's an importable module.
+The actual script to place in cgi-bin is faqw.py.
+
+"""
+
+import sys, time, os, stat, re, cgi, faqconf
+from faqconf import * # This imports all uppercase names
+now = time.time()
+
+class FileError:
+ def __init__(self, file):
+ self.file = file
+
+class InvalidFile(FileError):
+ pass
+
+class NoSuchSection(FileError):
+ def __init__(self, section):
+ FileError.__init__(self, NEWFILENAME %(section, 1))
+ self.section = section
+
+class NoSuchFile(FileError):
+ def __init__(self, file, why=None):
+ FileError.__init__(self, file)
+ self.why = why
+
+def escape(s):
+ s = s.replace('&', '&')
+ s = s.replace('<', '&lt;')
+ s = s.replace('>', '&gt;')
+ return s
+
+def escapeq(s):
+ s = escape(s)
+ s = s.replace('"', '&quot;')
+ return s
+
+def _interpolate(format, args, kw):
+ try:
+ quote = kw['_quote']
+ except KeyError:
+ quote = 1
+ d = (kw,) + args + (faqconf.__dict__,)
+ m = MagicDict(d, quote)
+ return format % m
+
+def interpolate(format, *args, **kw):
+ return _interpolate(format, args, kw)
+
+def emit(format, *args, **kw):
+ try:
+ f = kw['_file']
+ except KeyError:
+ f = sys.stdout
+ f.write(_interpolate(format, args, kw))
+
+translate_prog = None
+
+def translate(text, pre=0):
+ global translate_prog
+ if not translate_prog:
+ translate_prog = prog = re.compile(
+ r'\b(http|ftp|https)://\S+(\b|/)|\b[-.\w]+@[-.\w]+')
+ else:
+ prog = translate_prog
+ i = 0
+ list = []
+ while 1:
+ m = prog.search(text, i)
+ if not m:
+ break
+ j = m.start()
+ list.append(escape(text[i:j]))
+ i = j
+ url = m.group(0)
+ while url[-1] in '();:,.?\'"<>':
+ url = url[:-1]
+ i = i + len(url)
+ url = escape(url)
+ if not pre or (pre and PROCESS_PREFORMAT):
+ if ':' in url:
+ repl = '<A HREF="%s">%s</A>' % (url, url)
+ else:
+ repl = '<A HREF="mailto:%s">%s</A>' % (url, url)
+ else:
+ repl = url
+ list.append(repl)
+ j = len(text)
+ list.append(escape(text[i:j]))
+ return ''.join(list)
+
+def emphasize(line):
+ return re.sub(r'\*([a-zA-Z]+)\*', r'<I>\1</I>', line)
+
+revparse_prog = None
+
+def revparse(rev):
+ global revparse_prog
+ if not revparse_prog:
+ revparse_prog = re.compile(r'^(\d{1,3})\.(\d{1,4})$')
+ m = revparse_prog.match(rev)
+ if not m:
+ return None
+ [major, minor] = map(int, m.group(1, 2))
+ return major, minor
+
+logon = 0
+def log(text):
+ if logon:
+ logfile = open("logfile", "a")
+ logfile.write(text + "\n")
+ logfile.close()
+
+def load_cookies():
+ if not os.environ.has_key('HTTP_COOKIE'):
+ return {}
+ raw = os.environ['HTTP_COOKIE']
+ words = [s.strip() for s in raw.split(';')]
+ cookies = {}
+ for word in words:
+ i = word.find('=')
+ if i >= 0:
+ key, value = word[:i], word[i+1:]
+ cookies[key] = value
+ return cookies
+
+def load_my_cookie():
+ cookies = load_cookies()
+ try:
+ value = cookies[COOKIE_NAME]
+ except KeyError:
+ return {}
+ import urllib
+ value = urllib.unquote(value)
+ words = value.split('/')
+ while len(words) < 3:
+ words.append('')
+ author = '/'.join(words[:-2])
+ email = words[-2]
+ password = words[-1]
+ return {'author': author,
+ 'email': email,
+ 'password': password}
+
+def send_my_cookie(ui):
+ name = COOKIE_NAME
+ value = "%s/%s/%s" % (ui.author, ui.email, ui.password)
+ import urllib
+ value = urllib.quote(value)
+ then = now + COOKIE_LIFETIME
+ gmt = time.gmtime(then)
+ path = os.environ.get('SCRIPT_NAME', '/cgi-bin/')
+ print "Set-Cookie: %s=%s; path=%s;" % (name, value, path),
+ print time.strftime("expires=%a, %d-%b-%y %X GMT", gmt)
+
+class MagicDict:
+
+ def __init__(self, d, quote):
+ self.__d = d
+ self.__quote = quote
+
+ def __getitem__(self, key):
+ for d in self.__d:
+ try:
+ value = d[key]
+ if value:
+ value = str(value)
+ if self.__quote:
+ value = escapeq(value)
+ return value
+ except KeyError:
+ pass
+ return ''
+
+class UserInput:
+
+ def __init__(self):
+ self.__form = cgi.FieldStorage()
+ #log("\n\nbody: " + self.body)
+
+ def __getattr__(self, name):
+ if name[0] == '_':
+ raise AttributeError
+ try:
+ value = self.__form[name].value
+ except (TypeError, KeyError):
+ value = ''
+ else:
+ value = value.strip()
+ setattr(self, name, value)
+ return value
+
+ def __getitem__(self, key):
+ return getattr(self, key)
+
+class FaqEntry:
+
+ def __init__(self, fp, file, sec_num):
+ self.file = file
+ self.sec, self.num = sec_num
+ if fp:
+ import rfc822
+ self.__headers = rfc822.Message(fp)
+ self.body = fp.read().strip()
+ else:
+ self.__headers = {'title': "%d.%d. " % sec_num}
+ self.body = ''
+
+ def __getattr__(self, name):
+ if name[0] == '_':
+ raise AttributeError
+ key = '-'.join(name.split('_'))
+ try:
+ value = self.__headers[key]
+ except KeyError:
+ value = ''
+ setattr(self, name, value)
+ return value
+
+ def __getitem__(self, key):
+ return getattr(self, key)
+
+ def load_version(self):
+ command = interpolate(SH_RLOG_H, self)
+ p = os.popen(command)
+ version = ''
+ while 1:
+ line = p.readline()
+ if not line:
+ break
+ if line[:5] == 'head:':
+ version = line[5:].strip()
+ p.close()
+ self.version = version
+
+ def getmtime(self):
+ if not self.last_changed_date:
+ return 0
+ try:
+ return os.stat(self.file)[stat.ST_MTIME]
+ except os.error:
+ return 0
+
+ def emit_marks(self):
+ mtime = self.getmtime()
+ if mtime >= now - DT_VERY_RECENT:
+ emit(MARK_VERY_RECENT, self)
+ elif mtime >= now - DT_RECENT:
+ emit(MARK_RECENT, self)
+
+ def show(self, edit=1):
+ emit(ENTRY_HEADER1, self)
+ self.emit_marks()
+ emit(ENTRY_HEADER2, self)
+ pre = 0
+ raw = 0
+ for line in self.body.split('\n'):
+ # Allow the user to insert raw html into a FAQ answer
+ # (Skip Montanaro, with changes by Guido)
+ tag = line.rstrip().lower()
+ if tag == '<html>':
+ raw = 1
+ continue
+ if tag == '</html>':
+ raw = 0
+ continue
+ if raw:
+ print line
+ continue
+ if not line.strip():
+ if pre:
+ print '</PRE>'
+ pre = 0
+ else:
+ print '<P>'
+ else:
+ if not line[0].isspace():
+ if pre:
+ print '</PRE>'
+ pre = 0
+ else:
+ if not pre:
+ print '<PRE>'
+ pre = 1
+ if '/' in line or '@' in line:
+ line = translate(line, pre)
+ elif '<' in line or '&' in line:
+ line = escape(line)
+ if not pre and '*' in line:
+ line = emphasize(line)
+ print line
+ if pre:
+ print '</PRE>'
+ pre = 0
+ if edit:
+ print '<P>'
+ emit(ENTRY_FOOTER, self)
+ if self.last_changed_date:
+ emit(ENTRY_LOGINFO, self)
+ print '<P>'
+
+class FaqDir:
+
+ entryclass = FaqEntry
+
+ __okprog = re.compile(OKFILENAME)
+
+ def __init__(self, dir=os.curdir):
+ self.__dir = dir
+ self.__files = None
+
+ def __fill(self):
+ if self.__files is not None:
+ return
+ self.__files = files = []
+ okprog = self.__okprog
+ for file in os.listdir(self.__dir):
+ if self.__okprog.match(file):
+ files.append(file)
+ files.sort()
+
+ def good(self, file):
+ return self.__okprog.match(file)
+
+ def parse(self, file):
+ m = self.good(file)
+ if not m:
+ return None
+ sec, num = m.group(1, 2)
+ return int(sec), int(num)
+
+ def list(self):
+ # XXX Caller shouldn't modify result
+ self.__fill()
+ return self.__files
+
+ def open(self, file):
+ sec_num = self.parse(file)
+ if not sec_num:
+ raise InvalidFile(file)
+ try:
+ fp = open(file)
+ except IOError, msg:
+ raise NoSuchFile(file, msg)
+ try:
+ return self.entryclass(fp, file, sec_num)
+ finally:
+ fp.close()
+
+ def show(self, file, edit=1):
+ self.open(file).show(edit=edit)
+
+ def new(self, section):
+ if not SECTION_TITLES.has_key(section):
+ raise NoSuchSection(section)
+ maxnum = 0
+ for file in self.list():
+ sec, num = self.parse(file)
+ if sec == section:
+ maxnum = max(maxnum, num)
+ sec_num = (section, maxnum+1)
+ file = NEWFILENAME % sec_num
+ return self.entryclass(None, file, sec_num)
+
+class FaqWizard:
+
+ def __init__(self):
+ self.ui = UserInput()
+ self.dir = FaqDir()
+
+ def go(self):
+ print 'Content-type: text/html'
+ req = self.ui.req or 'home'
+ mname = 'do_%s' % req
+ try:
+ meth = getattr(self, mname)
+ except AttributeError:
+ self.error("Bad request type %r." % (req,))
+ else:
+ try:
+ meth()
+ except InvalidFile, exc:
+ self.error("Invalid entry file name %s" % exc.file)
+ except NoSuchFile, exc:
+ self.error("No entry with file name %s" % exc.file)
+ except NoSuchSection, exc:
+ self.error("No section number %s" % exc.section)
+ self.epilogue()
+
+ def error(self, message, **kw):
+ self.prologue(T_ERROR)
+ emit(message, kw)
+
+ def prologue(self, title, entry=None, **kw):
+ emit(PROLOGUE, entry, kwdict=kw, title=escape(title))
+
+ def epilogue(self):
+ emit(EPILOGUE)
+
+ def do_home(self):
+ self.prologue(T_HOME)
+ emit(HOME)
+
+ def do_debug(self):
+ self.prologue("FAQ Wizard Debugging")
+ form = cgi.FieldStorage()
+ cgi.print_form(form)
+ cgi.print_environ(os.environ)
+ cgi.print_directory()
+ cgi.print_arguments()
+
+ def do_search(self):
+ query = self.ui.query
+ if not query:
+ self.error("Empty query string!")
+ return
+ if self.ui.querytype == 'simple':
+ query = re.escape(query)
+ queries = [query]
+ elif self.ui.querytype in ('anykeywords', 'allkeywords'):
+ words = filter(None, re.split('\W+', query))
+ if not words:
+ self.error("No keywords specified!")
+ return
+ words = map(lambda w: r'\b%s\b' % w, words)
+ if self.ui.querytype[:3] == 'any':
+ queries = ['|'.join(words)]
+ else:
+ # Each of the individual queries must match
+ queries = words
+ else:
+ # Default to regular expression
+ queries = [query]
+ self.prologue(T_SEARCH)
+ progs = []
+ for query in queries:
+ if self.ui.casefold == 'no':
+ p = re.compile(query)
+ else:
+ p = re.compile(query, re.IGNORECASE)
+ progs.append(p)
+ hits = []
+ for file in self.dir.list():
+ try:
+ entry = self.dir.open(file)
+ except FileError:
+ constants
+ for p in progs:
+ if not p.search(entry.title) and not p.search(entry.body):
+ break
+ else:
+ hits.append(file)
+ if not hits:
+ emit(NO_HITS, self.ui, count=0)
+ elif len(hits) <= MAXHITS:
+ if len(hits) == 1:
+ emit(ONE_HIT, count=1)
+ else:
+ emit(FEW_HITS, count=len(hits))
+ self.format_all(hits, headers=0)
+ else:
+ emit(MANY_HITS, count=len(hits))
+ self.format_index(hits)
+
+ def do_all(self):
+ self.prologue(T_ALL)
+ files = self.dir.list()
+ self.last_changed(files)
+ self.format_index(files, localrefs=1)
+ self.format_all(files)
+
+ def do_compat(self):
+ files = self.dir.list()
+ emit(COMPAT)
+ self.last_changed(files)
+ self.format_index(files, localrefs=1)
+ self.format_all(files, edit=0)
+ sys.exit(0) # XXX Hack to suppress epilogue
+
+ def last_changed(self, files):
+ latest = 0
+ for file in files:
+ entry = self.dir.open(file)
+ if entry:
+ mtime = mtime = entry.getmtime()
+ if mtime > latest:
+ latest = mtime
+ print time.strftime(LAST_CHANGED, time.localtime(latest))
+ emit(EXPLAIN_MARKS)
+
+ def format_all(self, files, edit=1, headers=1):
+ sec = 0
+ for file in files:
+ try:
+ entry = self.dir.open(file)
+ except NoSuchFile:
+ continue
+ if headers and entry.sec != sec:
+ sec = entry.sec
+ try:
+ title = SECTION_TITLES[sec]
+ except KeyError:
+ title = "Untitled"
+ emit("\n<HR>\n<H1>%(sec)s. %(title)s</H1>\n",
+ sec=sec, title=title)
+ entry.show(edit=edit)
+
+ def do_index(self):
+ self.prologue(T_INDEX)
+ files = self.dir.list()
+ self.last_changed(files)
+ self.format_index(files, add=1)
+
+ def format_index(self, files, add=0, localrefs=0):
+ sec = 0
+ for file in files:
+ try:
+ entry = self.dir.open(file)
+ except NoSuchFile:
+ continue
+ if entry.sec != sec:
+ if sec:
+ if add:
+ emit(INDEX_ADDSECTION, sec=sec)
+ emit(INDEX_ENDSECTION, sec=sec)
+ sec = entry.sec
+ try:
+ title = SECTION_TITLES[sec]
+ except KeyError:
+ title = "Untitled"
+ emit(INDEX_SECTION, sec=sec, title=title)
+ if localrefs:
+ emit(LOCAL_ENTRY, entry)
+ else:
+ emit(INDEX_ENTRY, entry)
+ entry.emit_marks()
+ if sec:
+ if add:
+ emit(INDEX_ADDSECTION, sec=sec)
+ emit(INDEX_ENDSECTION, sec=sec)
+
+ def do_recent(self):
+ if not self.ui.days:
+ days = 1
+ else:
+ days = float(self.ui.days)
+ try:
+ cutoff = now - days * 24 * 3600
+ except OverflowError:
+ cutoff = 0
+ list = []
+ for file in self.dir.list():
+ entry = self.dir.open(file)
+ if not entry:
+ continue
+ mtime = entry.getmtime()
+ if mtime >= cutoff:
+ list.append((mtime, file))
+ list.sort()
+ list.reverse()
+ self.prologue(T_RECENT)
+ if days <= 1:
+ period = "%.2g hours" % (days*24)
+ else:
+ period = "%.6g days" % days
+ if not list:
+ emit(NO_RECENT, period=period)
+ elif len(list) == 1:
+ emit(ONE_RECENT, period=period)
+ else:
+ emit(SOME_RECENT, period=period, count=len(list))
+ self.format_all(map(lambda (mtime, file): file, list), headers=0)
+ emit(TAIL_RECENT)
+
+ def do_roulette(self):
+ import random
+ files = self.dir.list()
+ if not files:
+ self.error("No entries.")
+ return
+ file = random.choice(files)
+ self.prologue(T_ROULETTE)
+ emit(ROULETTE)
+ self.dir.show(file)
+
+ def do_help(self):
+ self.prologue(T_HELP)
+ emit(HELP)
+
+ def do_show(self):
+ entry = self.dir.open(self.ui.file)
+ self.prologue(T_SHOW)
+ entry.show()
+
+ def do_add(self):
+ self.prologue(T_ADD)
+ emit(ADD_HEAD)
+ sections = SECTION_TITLES.items()
+ sections.sort()
+ for section, title in sections:
+ emit(ADD_SECTION, section=section, title=title)
+ emit(ADD_TAIL)
+
+ def do_delete(self):
+ self.prologue(T_DELETE)
+ emit(DELETE)
+
+ def do_log(self):
+ entry = self.dir.open(self.ui.file)
+ self.prologue(T_LOG, entry)
+ emit(LOG, entry)
+ self.rlog(interpolate(SH_RLOG, entry), entry)
+
+ def rlog(self, command, entry=None):
+ output = os.popen(command).read()
+ sys.stdout.write('<PRE>')
+ athead = 0
+ lines = output.split('\n')
+ while lines and not lines[-1]:
+ del lines[-1]
+ if lines:
+ line = lines[-1]
+ if line[:1] == '=' and len(line) >= 40 and \
+ line == line[0]*len(line):
+ del lines[-1]
+ headrev = None
+ for line in lines:
+ if entry and athead and line[:9] == 'revision ':
+ rev = line[9:].split()
+ mami = revparse(rev)
+ if not mami:
+ print line
+ else:
+ emit(REVISIONLINK, entry, rev=rev, line=line)
+ if mami[1] > 1:
+ prev = "%d.%d" % (mami[0], mami[1]-1)
+ emit(DIFFLINK, entry, prev=prev, rev=rev)
+ if headrev:
+ emit(DIFFLINK, entry, prev=rev, rev=headrev)
+ else:
+ headrev = rev
+ print
+ athead = 0
+ else:
+ athead = 0
+ if line[:1] == '-' and len(line) >= 20 and \
+ line == len(line) * line[0]:
+ athead = 1
+ sys.stdout.write('<HR>')
+ else:
+ print line
+ print '</PRE>'
+
+ def do_revision(self):
+ entry = self.dir.open(self.ui.file)
+ rev = self.ui.rev
+ mami = revparse(rev)
+ if not mami:
+ self.error("Invalid revision number: %r." % (rev,))
+ self.prologue(T_REVISION, entry)
+ self.shell(interpolate(SH_REVISION, entry, rev=rev))
+
+ def do_diff(self):
+ entry = self.dir.open(self.ui.file)
+ prev = self.ui.prev
+ rev = self.ui.rev
+ mami = revparse(rev)
+ if not mami:
+ self.error("Invalid revision number: %r." % (rev,))
+ if prev:
+ if not revparse(prev):
+ self.error("Invalid previous revision number: %r." % (prev,))
+ else:
+ prev = '%d.%d' % (mami[0], mami[1])
+ self.prologue(T_DIFF, entry)
+ self.shell(interpolate(SH_RDIFF, entry, rev=rev, prev=prev))
+
+ def shell(self, command):
+ output = os.popen(command).read()
+ sys.stdout.write('<PRE>')
+ print escape(output)
+ print '</PRE>'
+
+ def do_new(self):
+ entry = self.dir.new(section=int(self.ui.section))
+ entry.version = '*new*'
+ self.prologue(T_EDIT)
+ emit(EDITHEAD)
+ emit(EDITFORM1, entry, editversion=entry.version)
+ emit(EDITFORM2, entry, load_my_cookie())
+ emit(EDITFORM3)
+ entry.show(edit=0)
+
+ def do_edit(self):
+ entry = self.dir.open(self.ui.file)
+ entry.load_version()
+ self.prologue(T_EDIT)
+ emit(EDITHEAD)
+ emit(EDITFORM1, entry, editversion=entry.version)
+ emit(EDITFORM2, entry, load_my_cookie())
+ emit(EDITFORM3)
+ entry.show(edit=0)
+
+ def do_review(self):
+ send_my_cookie(self.ui)
+ if self.ui.editversion == '*new*':
+ sec, num = self.dir.parse(self.ui.file)
+ entry = self.dir.new(section=sec)
+ entry.version = "*new*"
+ if entry.file != self.ui.file:
+ self.error("Commit version conflict!")
+ emit(NEWCONFLICT, self.ui, sec=sec, num=num)
+ return
+ else:
+ entry = self.dir.open(self.ui.file)
+ entry.load_version()
+ # Check that the FAQ entry number didn't change
+ if self.ui.title.split()[:1] != entry.title.split()[:1]:
+ self.error("Don't change the entry number please!")
+ return
+ # Check that the edited version is the current version
+ if entry.version != self.ui.editversion:
+ self.error("Commit version conflict!")
+ emit(VERSIONCONFLICT, entry, self.ui)
+ return
+ commit_ok = ((not PASSWORD
+ or self.ui.password == PASSWORD)
+ and self.ui.author
+ and '@' in self.ui.email
+ and self.ui.log)
+ if self.ui.commit:
+ if not commit_ok:
+ self.cantcommit()
+ else:
+ self.commit(entry)
+ return
+ self.prologue(T_REVIEW)
+ emit(REVIEWHEAD)
+ entry.body = self.ui.body
+ entry.title = self.ui.title
+ entry.show(edit=0)
+ emit(EDITFORM1, self.ui, entry)
+ if commit_ok:
+ emit(COMMIT)
+ else:
+ emit(NOCOMMIT_HEAD)
+ self.errordetail()
+ emit(NOCOMMIT_TAIL)
+ emit(EDITFORM2, self.ui, entry, load_my_cookie())
+ emit(EDITFORM3)
+
+ def cantcommit(self):
+ self.prologue(T_CANTCOMMIT)
+ print CANTCOMMIT_HEAD
+ self.errordetail()
+ print CANTCOMMIT_TAIL
+
+ def errordetail(self):
+ if PASSWORD and self.ui.password != PASSWORD:
+ emit(NEED_PASSWD)
+ if not self.ui.log:
+ emit(NEED_LOG)
+ if not self.ui.author:
+ emit(NEED_AUTHOR)
+ if not self.ui.email:
+ emit(NEED_EMAIL)
+
+ def commit(self, entry):
+ file = entry.file
+ # Normalize line endings in body
+ if '\r' in self.ui.body:
+ self.ui.body = re.sub('\r\n?', '\n', self.ui.body)
+ # Normalize whitespace in title
+ self.ui.title = ' '.join(self.ui.title.split())
+ # Check that there were any changes
+ if self.ui.body == entry.body and self.ui.title == entry.title:
+ self.error("You didn't make any changes!")
+ return
+
+ # need to lock here because otherwise the file exists and is not writable (on NT)
+ command = interpolate(SH_LOCK, file=file)
+ p = os.popen(command)
+ output = p.read()
+
+ try:
+ os.unlink(file)
+ except os.error:
+ pass
+ try:
+ f = open(file, 'w')
+ except IOError, why:
+ self.error(CANTWRITE, file=file, why=why)
+ return
+ date = time.ctime(now)
+ emit(FILEHEADER, self.ui, os.environ, date=date, _file=f, _quote=0)
+ f.write('\n')
+ f.write(self.ui.body)
+ f.write('\n')
+ f.close()
+
+ import tempfile
+ tf = tempfile.NamedTemporaryFile()
+ emit(LOGHEADER, self.ui, os.environ, date=date, _file=tf)
+ tf.flush()
+ tf.seek(0)
+
+ command = interpolate(SH_CHECKIN, file=file, tfn=tf.name)
+ log("\n\n" + command)
+ p = os.popen(command)
+ output = p.read()
+ sts = p.close()
+ log("output: " + output)
+ log("done: " + str(sts))
+ log("TempFile:\n" + tf.read() + "end")
+
+ if not sts:
+ self.prologue(T_COMMITTED)
+ emit(COMMITTED)
+ else:
+ self.error(T_COMMITFAILED)
+ emit(COMMITFAILED, sts=sts)
+ print '<PRE>%s</PRE>' % escape(output)
+
+ try:
+ os.unlink(tf.name)
+ except os.error:
+ pass
+
+ entry = self.dir.open(file)
+ entry.show()
+
+wiz = FaqWizard()
+wiz.go()