]> granicus.if.org Git - python/commitdiff
Lots of new features:
authorGuido van Rossum <guido@python.org>
Wed, 21 May 1997 21:31:39 +0000 (21:31 +0000)
committerGuido van Rossum <guido@python.org>
Wed, 21 May 1997 21:31:39 +0000 (21:31 +0000)
- got rid of the separate search page
- added an index (lists the questions with links to the answers)
- add a mechanism to add new entries
- add a way to list most recently edited entries first

Tools/faqwiz/faqmain.py

index d1e6a55a338a74e4e0e4b3a62ac4fff6cd480834..bc02accd4794dd3519346bf1c8b825e7f69b34c0 100644 (file)
@@ -1,10 +1,32 @@
 #! /depot/sundry/plat/bin/python1.4
 
-"""Interactive FAQ project."""
+"""Interactive FAQ project.
+
+XXX TO DO
+
+- use cookies to keep Name/email the same
+- explanation of editing somewhere
+- various embellishments, GIFs, crosslinks, hints, etc.
+- create new sections
+- rearrange entries
+- delete entries
+- log changes
+- send email on changes
+- optional staging of entries until reviewed?
+- review revision log and older versions
+- freeze entries
+- username/password for editors
+- Change references to other Q's and whole sections
+- Browse should display menu of 7 sections & let you pick
+  (or frontpage should have the option to browse a section or all)
+- support adding annotations, too
+
+"""
 
 import cgi, string, os
 
 NAMEPAT = "faq??.???.htp"
+NAMEREG = "^faq\([0-9][0-9]\)\.\([0-9][0-9][0-9]\)\.htp$"
 
 class FAQServer:
 
@@ -22,7 +44,7 @@ class FAQServer:
            method()
 
     KEYS = ['req', 'query', 'name', 'text', 'commit', 'title',
-           'author', 'email', 'log']
+           'author', 'email', 'log', 'section', 'number', 'add']
 
     def __getattr__(self, key):
        if key not in self.KEYS:
@@ -38,12 +60,15 @@ class FAQServer:
        <TITLE>Python FAQ (alpha 1)</TITLE>
        <H1>Python FAQ Front Page</H1>
        <UL>
-       <LI><A HREF="faq.py?req=search">Search the FAQ</A>
-       <LI><A HREF="faq.py?req=browse">Browse the FAQ</A>
-       <LI><A HREF="faq.py?req=submit">Submit a new FAQ entry</A> (not yet)
+       <LI><A HREF="faq.py?req=index">FAQ index</A>
+       <LI><A HREF="faq.py?req=all">The whole FAQ</A>
        <LI><A HREF="faq.py?req=roulette">FAQ roulette</A>
+       <LI><A HREF="faq.py?req=recent">Recently changed FAQ entries</A>
+       <LI><A HREF="faq.py?req=add">Add a new FAQ entry</A>
        </UL>
 
+       <H2>Search the FAQ</H2>
+
        <FORM ACTION="faq.py?req=query">
        <INPUT TYPE=text NAME=query>
        <INPUT TYPE=submit VALUE="Search">
@@ -54,7 +79,52 @@ class FAQServer:
        Please exercise discretion when editing, don't be rude, etc.
        """
 
-    def do_browse(self):
+    def do_index(self):
+       print """
+       <TITLE>Python FAQ Index</TITLE>
+       <H1>Python FAQ Index</H1>
+       """
+       names = os.listdir(os.curdir)
+       names.sort()
+       section = None
+       for name in names:
+           headers, text = self.read(name)
+           if headers:
+               title = headers['title']
+               i = string.find(title, '.')
+               nsec = title[:i]
+               if nsec != section:
+                   if section:
+                       print """
+                       <P>
+                       <LI><A HREF="faq.py?req=add&amp;section=%s"
+                       >Add new entry</A> (at this point)
+                       </UL>
+                       """ % section
+                   section = nsec
+                   print "<H2>Section %s</H2>" % section
+                   print "<UL>"
+               print '<LI><A HREF="faq.py?req=show&name=%s">%s</A>' % (
+                   name, cgi.escape(title))
+       if section:
+           print """
+           <P>
+           <LI><A HREF="faq.py?req=add&amp;section=%s">Add new entry</A>
+           (at this point)
+           </UL>
+           """ % section
+       else:
+           print "No FAQ entries?!?!"
+
+    def do_show(self):
+       name = self.name
+       headers, text = self.read(name)
+       if not headers:
+           print "Invalid file name", name
+           return
+       self.show(name, headers['title'], text, 1)
+
+    def do_all(self):
        print """
        <TITLE>Python FAQ</TITLE>
        <H1>Python FAQ</H1>
@@ -62,13 +132,20 @@ class FAQServer:
        """
        names = os.listdir(os.curdir)
        names.sort()
-       n = 0
+       section = None
        for name in names:
            headers, text = self.read(name)
            if headers:
-               self.show(name, headers['title'], text, 1)
+               title = headers['title']
+               i = string.find(title, '.')
+               nsec = title[:i]
+               if nsec != section:
+                   section = nsec
+                   print "<H1>Section %s</H1>" % section
+                   print "<HR>"
+               self.show(name, title, text, 1)
                n = n+1
-       if not n:
+       if not section:
            print "No FAQ entries?!?!"
 
     def do_roulette(self):
@@ -94,17 +171,35 @@ class FAQServer:
        else:
            print "No FAQ entries?!?!"
 
-    def do_search(self):
+    def do_recent(self):
+       import fnmatch, stat
+       names = os.listdir(os.curdir)
+       now = time.time()
+       list = []
+       for name in names:
+           if not fnmatch.fnmatch(name, NAMEPAT):
+               continue
+           try:
+               st = os.stat(name)
+           except os.error:
+               continue
+           tuple = (st[stat.ST_MTIME], name)
+           list.append(tuple)
+       list.sort()
+       list.reverse()
        print """
-       <TITLE>Search the Python FAQ</TITLE>
-       <H1>Search the Python FAQ</H1>
-
-       <FORM ACTION="faq.py?req=query">
-       <INPUT TYPE=text NAME=query>
-       <INPUT TYPE=submit VALUE="Search">
-       <INPUT TYPE=hidden NAME=req VALUE=query>
-       </FORM>
+       <TITLE>Python FAQ, Most Recently Modified First</TITLE>
+       <H1>Python FAQ, Most Recently Modified First</H1>
+       <HR>
        """
+       n = 0
+       for (mtime, name) in list:
+           headers, text = self.read(name)
+           if headers:
+               self.show(name, headers['title'], text, 1)
+               n = n+1
+       if not n:
+           print "No FAQ entries?!?!"
 
     def do_query(self):
        import regex
@@ -129,6 +224,43 @@ class FAQServer:
        if not n:
            print "No hits."
 
+    def do_add(self):
+       section = self.section
+       if not section:
+           print """
+           <TITLE>How to add a new FAQ entry</TITLE>
+           <H1>How to add a new FAQ entry</H1>
+
+           Go to the <A HREF="faq.py?req=index">FAQ index</A>
+           and click on the "Add new entry" link at the end
+           of the section to which you want to add the entry.
+           """
+           return
+       try:
+           nsec = string.atoi(section)
+       except ValueError:
+           print "Bad section number", nsec
+       names = os.listdir(os.curdir)
+       max = 0
+       import regex
+       prog = regex.compile(NAMEREG)
+       for name in names:
+           if prog.match(name) >= 0:
+               s1, s2 = prog.group(1, 2)
+               n1, n2 = string.atoi(s1), string.atoi(s2)
+               if n1 == nsec:
+                   if n2 > max:
+                       max = n2
+       if not max:
+           print "Can't add new sections yet."
+           return
+       num = max+1
+       name = "faq%02d.%03d.htp" % (nsec, num)
+       self.name = name
+       self.add = "yes"
+       self.number = str(num)
+       self.do_edit()
+
     def do_edit(self):
        name = self.name
        headers, text = self.read(name)
@@ -141,7 +273,13 @@ class FAQServer:
        """
        title = headers['title']
        print "<FORM METHOD=POST ACTION=faq.py>"
-       self.showedit(name, headers, text)
+       self.showedit(name, title, text)
+       if self.add:
+           print """
+           <INPUT TYPE=hidden NAME=add VALUE=%s>
+           <INPUT TYPE=hidden NAME=section VALUE=%s>
+           <INPUT TYPE=hidden NAME=number VALUE=%s>
+           """ % (self.add, self.section, self.number)
        print """
        <INPUT TYPE=submit VALUE="Review Edit">
        <INPUT TYPE=hidden NAME=req VALUE=review>
@@ -165,6 +303,7 @@ class FAQServer:
        print """
        <TITLE>Python FAQ Review Form</TITLE>
        <H1>Python FAQ Review Form</H1>
+       <HR>
        """
        self.show(name, title, text)
        print "<FORM METHOD=POST ACTION=faq.py>"
@@ -184,7 +323,13 @@ class FAQServer:
            <HR>
            <P>
            """
-       self.showedit(name, headers, text)
+       self.showedit(name, title, text)
+       if self.add:
+           print """
+           <INPUT TYPE=hidden NAME=add VALUE=%s>
+           <INPUT TYPE=hidden NAME=section VALUE=%s>
+           <INPUT TYPE=hidden NAME=number VALUE=%s>
+           """ % (self.add, self.section, self.number)
        print """
        <BR>
        <INPUT TYPE=submit VALUE="Review Edit">
@@ -220,9 +365,9 @@ class FAQServer:
            print "No changes."
            # XXX Should exit more ceremoniously
            return
-       # Check that the question number didn't change
+       # Check that the FAQ entry number didn't change
        if string.split(title)[:1] != string.split(oldtitle)[:1]:
-           print "Don't change the question number please."
+           print "Don't change the FAQ entry number please."
            # XXX Should exit more ceremoniously
            return
        remhost = os.environ["REMOTE_HOST"]
@@ -285,6 +430,7 @@ class FAQServer:
        sts = p.close()
        if not sts:
            print """
+           <TITLE>Python FAQ Entry Edited</TITLE>
            <H1>Python FAQ Entry Edited</H1>
            <HR>
            """
@@ -299,8 +445,7 @@ class FAQServer:
            if output:
                print "<PRE>%s</PRE>" % cgi.escape(output)
 
-    def showedit(self, name, headers, text):
-       title = headers['title']
+    def showedit(self, name, title, text):
        print """
        Title: <INPUT TYPE=text SIZE=70 NAME=title VALUE="%s"<BR>
        <TEXTAREA COLS=80 ROWS=20 NAME=text>""" % title
@@ -328,6 +473,17 @@ class FAQServer:
        import fnmatch, rfc822
        if not fnmatch.fnmatch(name, NAMEPAT):
            return None, None
+       if self.add:
+           try:
+               fname = "faq%02d.%03d.htp" % (string.atoi(self.section),
+                                             string.atoi(self.number))
+           except ValueError:
+               return None, None
+           if fname != name:
+               return None, None
+           headers = {'title': "%s.%s. " % (self.section, self.number)}
+           text = ""
+           return headers, text
        f = open(name)
        headers = rfc822.Message(f)
        text = f.read()
@@ -337,7 +493,7 @@ class FAQServer:
     def show(self, name, title, text, edit=0):
        # XXX Should put <A> tags around recognizable URLs
        # XXX Should also turn "see section N" into hyperlinks
-       print "<H2>%s</H2>" % title
+       print "<H2>%s</H2>" % cgi.escape(title)
        pre = 0
        for line in string.split(text, '\n'):
            if not string.strip(line):
@@ -355,7 +511,7 @@ class FAQServer:
                    if not pre:
                        print '<PRE>'
                        pre = 1
-               print line
+               print cgi.escape(line)
        if pre:
            print '</PRE>'
            pre = 0
@@ -378,4 +534,4 @@ try:
 except:
     print "<HR>Sorry, an error occurred"
     cgi.print_exception()
-print "<!-- dt = %s -->" % str(round(dt, 3))
+print "<P>(time = %s seconds)" % str(round(dt, 3))