blob: 995cd3c821be91d1c62a0716d25ef9a76aaf8534 [file] [log] [blame]
Guido van Rossumadb3a9d1997-05-21 07:24:50 +00001#! /depot/sundry/plat/bin/python1.4
2
3"""Interactive FAQ project."""
4
5import cgi, string, os
6
7NAMEPAT = "faq??.???.htp"
8
9class FAQServer:
10
11 def __init__(self):
12 pass
13
14 def main(self):
15 self.form = cgi.FieldStorage()
16 req = self.req or 'frontpage'
17 try:
18 method = getattr(self, 'do_%s' % req)
19 except AttributeError:
20 print "Unrecognized request type", req
21 else:
22 method()
23
24 KEYS = ['req', 'query', 'name', 'text', 'commit', 'title']
25
26 def __getattr__(self, key):
27 if key not in self.KEYS:
28 raise AttributeError
29 if self.form.has_key(key):
30 item = self.form[key]
31 return item.value
32 return ''
33
34 def do_frontpage(self):
35 print """
36 <TITLE>Python FAQ (alpha 1)</TITLE>
37 <H1>Python FAQ Front Page</H1>
38 <UL>
39 <LI><A HREF="faq.py?req=search">Search the FAQ</A>
40 <LI><A HREF="faq.py?req=browse">Browse the FAQ</A>
41 <LI><A HREF="faq.py?req=submit">Submit a new FAQ entry</A>
42 <LI><A HREF="faq.py?req=roulette">Random FAQ entry</A>
43 </UL>
44
45 <FORM ACTION="faq.py?req=query">
46 <INPUT TYPE=text NAME=query>
47 <INPUT TYPE=submit VALUE="Search">
48 <INPUT TYPE=hidden NAME=req VALUE=query>
49 </FORM>
50
51 Disclaimer: these pages are intended to be edited by anyone.
52 Please exercise discretion when editing, don't be rude, etc.
53 """
54
55 def do_browse(self):
56 print """
57 <TITLE>Python FAQ</TITLE>
58 <H1>Python FAQ</H1>
59 <HR>
60 """
61 names = os.listdir(os.curdir)
62 names.sort()
63 n = 0
64 for name in names:
65 headers, body = self.read(name)
66 if headers:
67 self.show(name, headers, body, 1)
68 n = n+1
69 if not n:
70 print "No FAQ entries?!?!"
71
72 def do_roulette(self):
73 import whrandom
74 print """
75 <TITLE>Python FAQ Roulette</TITLE>
76 <H1>Python FAQ Roulette</H1>
77 Please check the correctness of the entry below.
78 If you find any problems, please edit the entry.
79 <P>
80 <HR>
81 """
82 names = os.listdir(os.curdir)
83 while names:
84 name = whrandom.choice(names)
85 headers, body = self.read(name)
86 if headers:
87 self.show(name, headers, body, 1)
88 print '<P><A HREF="faq.py?req=roulette">Show another one</A>'
89 break
90 else:
91 names.remove(name)
92 else:
93 print "No FAQ entries?!?!"
94
95 def do_search(self):
96 print """
97 <TITLE>Search the Python FAQ</TITLE>
98 <H1>Search the Python FAQ</H1>
99
100 <FORM ACTION="faq.py?req=query">
101 <INPUT TYPE=text NAME=query>
102 <INPUT TYPE=submit VALUE="Search">
103 <INPUT TYPE=hidden NAME=req VALUE=query>
104 </FORM>
105 """
106
107 def do_query(self):
108 import regex
109 print "<TITLE>Python FAQ Query Results</TITLE>"
110 print "<H1>Python FAQ Query Results</H1>"
111 query = self.query
112 if not query:
113 print "No query string"
114 return
115 p = regex.compile(query, regex.casefold)
116 names = os.listdir(os.curdir)
117 names.sort()
118 print "<HR>"
119 n = 0
120 for name in names:
121 headers, body = self.read(name)
122 if headers:
123 title = headers['title']
124 if p.search(title) >= 0 or p.search(body) >= 0:
125 self.show(name, headers, body, 1)
126 n = n+1
127 if not n:
128 print "No hits."
129
130 def do_edit(self):
131 name = self.name
132 headers, body = self.read(name)
133 if not headers:
134 print "Invalid file name", name
135 return
136 print """
137 <TITLE>Python FAQ Edit Form</TITLE>
138 <H1>Python FAQ Edit Form</H1>
139 """
140 self.showheaders(headers)
141 title = headers['title']
142 print """
143 <FORM METHOD=POST ACTION=faq.py>
144 <INPUT TYPE=text SIZE=80 NAME=title VALUE="%s"<BR>
145 <TEXTAREA COLS=80 ROWS=20 NAME=text>""" % title
146 print cgi.escape(string.strip(body))
147 print """</TEXTAREA>
148 <BR>
149 <INPUT TYPE=submit VALUE="Review Edit">
150 <INPUT TYPE=hidden NAME=req VALUE=review>
151 <INPUT TYPE=hidden NAME=name VALUE=%s>
152 </FORM>
153 <HR>
154 """ % name
155 self.show(name, headers, body)
156
157 def do_review(self):
158 name = self.name
159 text = self.text
160 commit = self.commit
161 title = self.title
162 if commit:
163 self.precheckin(name, text, title)
164 return
165 headers, body = self.read(name)
166 if not headers:
167 print "Invalid file name", name
168 return
169 print """
170 <TITLE>Python FAQ Review Form</TITLE>
171 <H1>Python FAQ Review Form</H1>
172 """
173 self.show(name, {'title': title}, text)
174 print """
175 <FORM METHOD=POST ACTION=faq.py>
176 <INPUT TYPE=submit NAME=commit VALUE="Commit">
177 <P>
178 <HR>
179 """
180 self.showheaders(headers)
181 print """
182 <INPUT TYPE=text SIZE=80 NAME=title VALUE="%s"<BR>
183 <TEXTAREA COLS=80 ROWS=20 NAME=text>""" % title
184 print cgi.escape(string.strip(text))
185 print """</TEXTAREA>
186 <BR>
187 <INPUT TYPE=submit VALUE="Review Edit">
188 <INPUT TYPE=hidden NAME=req VALUE=review>
189 <INPUT TYPE=hidden NAME=name VALUE=%s>
190 </FORM>
191 <HR>
192 """ % name
193
194 def precheckin(self, name, text, title):
195 pass
196
197 def showheaders(self, headers):
198 print "<UL>"
199 keys = map(string.lower, headers.keys())
200 keys.sort()
201 for key in keys:
202 print "<LI><B>%s:</B> %s" % (string.capwords(key, '-'),
203 headers[key] or '')
204 print "</UL>"
205
206 def read(self, name):
207 import fnmatch, rfc822
208 if not fnmatch.fnmatch(name, NAMEPAT):
209 return None, None
210 f = open(name)
211 headers = rfc822.Message(f)
212 body = f.read()
213 f.close()
214 return headers, body
215
216 def show(self, name, headers, body, edit=0):
217 # XXX Should put <A> tags around recognizable URLs
218 # XXX Should also turn "see section N" into hyperlinks
219 title = headers['title']
220 print "<H2>%s</H2>" % title
221 pre = 0
222 for line in string.split(body, '\n'):
223 if not string.strip(line):
224 if pre:
225 print '</PRE>'
226 pre = 0
227 else:
228 print '<P>'
229 else:
230 if line == string.lstrip(line):
231 if pre:
232 print '</PRE>'
233 pre = 0
234 else:
235 if not pre:
236 print '<PRE>'
237 pre = 1
238 print line
239 if pre:
240 print '</PRE>'
241 pre = 0
242 print '<P>'
243 if edit:
244 print '<A HREF="faq.py?req=edit&name=%s">Edit this entry</A>' %name
245 print '<P>'
246 print "<HR>"
247
248
249print "Content-type: text/html\n"
250try:
251 x = FAQServer()
252 x.main()
253except:
254 print "<HR>Sorry, an error occurred"
255 cgi.print_exception()