88
99XXX User Features TO DO
1010
11- - next/prev/index links in do_show?
11+ - next/prev/index links in do_show???
1212- explanation of editing somewhere
13- - embellishments, GIFs, crosslinks, hints, etc.
14- - make references to other Q's and whole sections into links
13+ - embellishments, GIFs, hints, etc.
1514- support adding annotations, too
15+ - restrict recent changes to last week (or make it an option)
16+ - extended search capabilities
1617
1718XXX Management Features TO DO
1819
20+ - username/password for authors
1921- create new sections
2022- rearrange entries
2123- delete entries
24+ - freeze entries
2225- send email on changes?
2326- send email on ERRORS!
2427- optional staging of entries until reviewed?
25- - freeze entries
26- - username/password for authors
27- - read section titles from a file (could be a Python file: import faqcustom)
28+ (could be done using rcs branches!)
29+ - prevent race conditions on nearly simultaneous commits
30+
31+ XXX Performance
32+
33+ - could cache generated HTML
34+ - could speed up searches with a separate index file
2835
2936XXX Code organization TO DO
3037
38+ - read section titles from a file (could be a Python file: import faqcustom)
3139- customize rcs command pathnames (and everything else)
3240- make it more generic (so you can create your own FAQ)
3341- more OO structure, e.g. add a class representing one FAQ entry
3442
3543"""
3644
45+ # NB for timing purposes, the imports are at the end of this file
46+
3747NAMEPAT = "faq??.???.htp"
3848NAMEREG = "^faq\([0-9][0-9]\)\.\([0-9][0-9][0-9]\)\.htp$"
3949
@@ -160,11 +170,24 @@ def do_show(self):
160170 self .show (name , headers ['title' ], text )
161171
162172 def do_all (self ):
173+ import fnmatch , stat
163174 self .prologue ("The Whole Python FAQ" )
164- print "<HR>"
165175 names = os .listdir (os .curdir )
176+ lastmtime = 0
177+ for name in names :
178+ if not fnmatch .fnmatch (name , NAMEPAT ):
179+ continue
180+ try :
181+ st = os .stat (name )
182+ except os .error :
183+ continue
184+ lastmtime = max (lastmtime , st [stat .ST_MTIME ])
185+ if lastmtime :
186+ print time .strftime ("Last changed on %c %Z" ,
187+ time .localtime (lastmtime ))
166188 names .sort ()
167189 section = None
190+ print "<HR>"
168191 for name in names :
169192 headers , text = self .read (name )
170193 if headers :
@@ -419,10 +442,23 @@ def checkin(self):
419442 version = self .version
420443 curversion = self .getversion (name )
421444 if version != curversion :
422- self .error ("Version conflict." ,
423- "You edited version %s but current version is %s." % (
424- version , curversion ),
425- '<A HREF="faq.py?req=show&name=%s">Reload.</A>' % name )
445+ self .error (
446+ "Version conflict." ,
447+ "You edited version %s but current version is %s." % (
448+ version , curversion ),
449+ """
450+ <P>
451+ The two most common causes of this problem are:
452+ <UL>
453+ <LI>After committing a change, you went back in your browser,
454+ edited the entry some more, and clicked Commit again.
455+ <LI>Someone else started editing the same entry and committed
456+ before you did.
457+ </UL>
458+ <P>
459+ """ ,
460+ '<A HREF="faq.py?req=show&name=%s"' % name ,
461+ '>Click here to reload the entry and try again.</A>' )
426462 return
427463 text = self .text
428464 title = self .title
@@ -494,6 +530,16 @@ def checkin(self):
494530 f .write (log )
495531 f .write ("\n " )
496532 f .close ()
533+
534+ # Do this for show() below
535+ self .headers = {
536+ 'title' : title ,
537+ 'last-changed-date' : now ,
538+ 'last-changed-author' : author ,
539+ 'last-changed-email' : email ,
540+ 'last-changed-remote-host' : remhost ,
541+ 'last-changed-remote-address' : remaddr ,
542+ }
497543
498544 p = os .popen ("""
499545 /depot/gnu/plat/bin/rcs -l %s </dev/null 2>&1
@@ -514,8 +560,6 @@ def checkin(self):
514560 "Exit status 0x%04x" % sts )
515561 if output :
516562 print "<PRE>%s</PRE>" % cgi .escape (output )
517- print '<HR>'
518- print '<A HREF="faq.py?req=show&name=%s">Reload this entry.</A>' % name
519563
520564 def set_cookie (self , author , email ):
521565 name = "Python-FAQ-ID"
@@ -558,19 +602,19 @@ def showedit(self, name, title, text):
558602 email = email or e
559603 print """
560604 Title: <INPUT TYPE=text SIZE=70 NAME=title VALUE="%s"><BR>
561- <TEXTAREA COLS=80 ROWS=20 NAME=text>""" % self .escape (title )
562- print cgi .escape (string .strip (text ))
563- print """</TEXTAREA>
605+ <TEXTAREA COLS=80 ROWS=20 NAME=text>%s</TEXTAREA>
606+ """ % (self .escape (title ), cgi .escape (string .strip (text )))
607+ print """
608+ <BR>
609+ Log message (reason for the change):<BR>
610+ <TEXTAREA COLS=80 ROWS=5 NAME=log>%s\n </TEXTAREA>
564611 <BR>
565612 Please provide the following information for logging purposes:
566613 <BR>
567614 <CODE>Name : </CODE><INPUT TYPE=text SIZE=40 NAME=author VALUE="%s">
568615 <BR>
569616 <CODE>Email: </CODE><INPUT TYPE=text SIZE=40 NAME=email VALUE="%s">
570- <BR>
571- Log message (reason for the change):<BR>
572- <TEXTAREA COLS=80 ROWS=5 NAME=log>%s\n </TEXTAREA>
573- """ % (self .escape (author ), self .escape (email ), self .escape (self .log ))
617+ """ % (self .escape (self .log ), self .escape (author ), self .escape (email ))
574618
575619 def escape (self , s ):
576620 import regsub
@@ -619,8 +663,6 @@ def read(self, name):
619663 return headers , text
620664
621665 def show (self , name , title , text , edit = 1 ):
622- # XXX Should put <A> tags around recognizable URLs
623- # XXX Should also turn "see section N" into hyperlinks
624666 print "<H2>%s</H2>" % cgi .escape (title )
625667 pre = 0
626668 for line in string .split (text , '\n ' ):
@@ -765,7 +807,7 @@ def emphasize(self, line):
765807
766808print "Content-type: text/html"
767809dt = 0
768- wanttime = 1
810+ wanttime = 0
769811try :
770812 import time
771813 t1 = time .time ()
@@ -774,6 +816,7 @@ def emphasize(self, line):
774816 x .main ()
775817 t2 = time .time ()
776818 dt = t2 - t1
819+ wanttime = 1
777820except :
778821 print "\n <HR>Sorry, an error occurred"
779822 cgi .print_exception ()
0 commit comments