105267
|
1 # Test file for Python language.
|
|
2 #
|
|
3
|
|
4 # Simle class compount statement with blank lines sprinkled.
|
|
5 class Foo(Bar):
|
|
6
|
|
7 x = 1
|
|
8
|
|
9 y = 2
|
|
10
|
|
11 # Simple def statement with no argument
|
|
12 def sss():
|
|
13 i = 1
|
|
14
|
|
15 # Simple def statement with arguments
|
|
16 def ttt(x,y,z):
|
|
17 i = 1
|
|
18
|
|
19 import foo
|
|
20
|
|
21 for x in y:
|
|
22 print x
|
|
23
|
|
24 while y > 0:
|
|
25 y = y - 1
|
|
26
|
|
27 a=b=c=d=e=f=i=j=k=l=m=n=o=p=q=r=s=t=x=y=1
|
|
28
|
|
29 if x:
|
|
30 x = 2
|
|
31 y = 3
|
|
32
|
|
33 x = 2
|
|
34 y = 3
|
|
35 s and t
|
|
36 q | r
|
|
37 o ^ p
|
|
38 m & n
|
|
39 k << l
|
|
40 z = 4
|
|
41 i >> j
|
|
42 e / f
|
|
43 c * d
|
|
44 a + b
|
|
45 2 ** 5
|
|
46 x
|
|
47 s = "a" "b" "c"
|
|
48 1
|
|
49
|
|
50 # implicit continuation lines, see
|
|
51 # http://docs.python.org/ref/implicit-joining.html
|
|
52
|
|
53 a_list = [ 1, 2, 3,
|
|
54 4, 5,
|
|
55 6 ]
|
|
56
|
|
57 a_tuple = (1, 2, 3,
|
|
58
|
|
59 4, 5, 6)
|
|
60
|
|
61 a_hash = { 'a':1, "b":2,
|
|
62 'c' : 3,
|
|
63 "d" : 4 }
|
|
64
|
|
65
|
|
66 def longarglist(a,
|
|
67 b,
|
|
68 c,
|
|
69 d):
|
|
70 a=1;
|
|
71 b=1;
|
|
72 c=1;
|
|
73 d=1;
|
|
74
|
|
75 class longclasslist(xx.yyy,
|
|
76 zz.aa):
|
|
77 foo=1
|
|
78
|
|
79
|
|
80 # wisent-python.wy chokes on this! -ryk 6/17/02
|
|
81
|
|
82 class HTTPServer(xxx.yyy):
|
|
83 allow_reuse_address = 1 # Seems to make sense in testing environment
|
|
84 def server_bind(self):
|
|
85 SocketServer.TCPServer.server_bind(self)
|
|
86 host, port = self.socket.getsockname()
|
|
87 self.server_name = socket.getfqdn(host)
|
|
88 self.server_port = port
|
|
89
|
|
90
|
|
91 #########################################################################
|
|
92 ### /usr/lib/python2.2/BaseHTTPServer.py
|
|
93 #########################################################################
|
|
94
|
|
95 """HTTP server base class.
|
|
96
|
|
97 Note: the class in this module doesn't implement any HTTP request; see
|
|
98 SimpleHTTPServer for simple implementations of GET, HEAD and POST
|
|
99 (including CGI scripts).
|
|
100
|
|
101 Contents:
|
|
102
|
|
103 - BaseHTTPRequestHandler: HTTP request handler base class
|
|
104 - test: test function
|
|
105
|
|
106 XXX To do:
|
|
107
|
|
108 - send server version
|
|
109 - log requests even later (to capture byte count)
|
|
110 - log user-agent header and other interesting goodies
|
|
111 - send error log to separate file
|
|
112 - are request names really case sensitive?
|
|
113
|
|
114 """
|
|
115
|
|
116
|
|
117 # See also:
|
|
118 #
|
|
119 # HTTP Working Group T. Berners-Lee
|
|
120 # INTERNET-DRAFT R. T. Fielding
|
|
121 # <draft-ietf-http-v10-spec-00.txt> H. Frystyk Nielsen
|
|
122 # Expires September 8, 1995 March 8, 1995
|
|
123 #
|
|
124 # URL: http://www.ics.uci.edu/pub/ietf/http/draft-ietf-http-v10-spec-00.txt
|
|
125
|
|
126
|
|
127 # Log files
|
|
128 # ---------
|
|
129 #
|
|
130 # Here's a quote from the NCSA httpd docs about log file format.
|
|
131 #
|
|
132 # | The logfile format is as follows. Each line consists of:
|
|
133 # |
|
|
134 # | host rfc931 authuser [DD/Mon/YYYY:hh:mm:ss] "request" ddd bbbb
|
|
135 # |
|
|
136 # | host: Either the DNS name or the IP number of the remote client
|
|
137 # | rfc931: Any information returned by identd for this person,
|
|
138 # | - otherwise.
|
|
139 # | authuser: If user sent a userid for authentication, the user name,
|
|
140 # | - otherwise.
|
|
141 # | DD: Day
|
|
142 # | Mon: Month (calendar name)
|
|
143 # | YYYY: Year
|
|
144 # | hh: hour (24-hour format, the machine's timezone)
|
|
145 # | mm: minutes
|
|
146 # | ss: seconds
|
|
147 # | request: The first line of the HTTP request as sent by the client.
|
|
148 # | ddd: the status code returned by the server, - if not available.
|
|
149 # | bbbb: the total number of bytes sent,
|
|
150 # | *not including the HTTP/1.0 header*, - if not available
|
|
151 # |
|
|
152 # | You can determine the name of the file accessed through request.
|
|
153 #
|
|
154 # (Actually, the latter is only true if you know the server configuration
|
|
155 # at the time the request was made!)
|
|
156
|
|
157
|
|
158 __version__ = "0.2"
|
|
159
|
|
160 __all__ = ["HTTPServer", "BaseHTTPRequestHandler"]
|
|
161
|
|
162 import sys
|
|
163 import time
|
|
164 import socket # For gethostbyaddr()
|
|
165 import mimetools
|
|
166 import SocketServer
|
|
167
|
|
168 # Default error message
|
|
169 DEFAULT_ERROR_MESSAGE = """\
|
|
170 <head>
|
|
171 <title>Error response</title>
|
|
172 </head>
|
|
173 <body>
|
|
174 <h1>Error response</h1>
|
|
175 <p>Error code %(code)d.
|
|
176 <p>Message: %(message)s.
|
|
177 <p>Error code explanation: %(code)s = %(explain)s.
|
|
178 </body>
|
|
179 """
|
|
180
|
|
181
|
|
182 class HTTPServer(SocketServer.TCPServer):
|
|
183
|
|
184 allow_reuse_address = 1 # Seems to make sense in testing environment
|
|
185
|
|
186 def server_bind(self):
|
|
187 """Override server_bind to store the server name."""
|
|
188 SocketServer.TCPServer.server_bind(self)
|
|
189 host, port = self.socket.getsockname()
|
|
190 self.server_name = socket.getfqdn(host)
|
|
191 self.server_port = port
|
|
192
|
|
193
|
|
194 class BaseHTTPRequestHandler(SocketServer.StreamRequestHandler):
|
|
195
|
|
196 """HTTP request handler base class.
|
|
197
|
|
198 The following explanation of HTTP serves to guide you through the
|
|
199 code as well as to expose any misunderstandings I may have about
|
|
200 HTTP (so you don't need to read the code to figure out I'm wrong
|
|
201 :-).
|
|
202
|
|
203 HTTP (HyperText Transfer Protocol) is an extensible protocol on
|
|
204 top of a reliable stream transport (e.g. TCP/IP). The protocol
|
|
205 recognizes three parts to a request:
|
|
206
|
|
207 1. One line identifying the request type and path
|
|
208 2. An optional set of RFC-822-style headers
|
|
209 3. An optional data part
|
|
210
|
|
211 The headers and data are separated by a blank line.
|
|
212
|
|
213 The first line of the request has the form
|
|
214
|
|
215 <command> <path> <version>
|
|
216
|
|
217 where <command> is a (case-sensitive) keyword such as GET or POST,
|
|
218 <path> is a string containing path information for the request,
|
|
219 and <version> should be the string "HTTP/1.0". <path> is encoded
|
|
220 using the URL encoding scheme (using %xx to signify the ASCII
|
|
221 character with hex code xx).
|
|
222
|
|
223 The protocol is vague about whether lines are separated by LF
|
|
224 characters or by CRLF pairs -- for compatibility with the widest
|
|
225 range of clients, both should be accepted. Similarly, whitespace
|
|
226 in the request line should be treated sensibly (allowing multiple
|
|
227 spaces between components and allowing trailing whitespace).
|
|
228
|
|
229 Similarly, for output, lines ought to be separated by CRLF pairs
|
|
230 but most clients grok LF characters just fine.
|
|
231
|
|
232 If the first line of the request has the form
|
|
233
|
|
234 <command> <path>
|
|
235
|
|
236 (i.e. <version> is left out) then this is assumed to be an HTTP
|
|
237 0.9 request; this form has no optional headers and data part and
|
|
238 the reply consists of just the data.
|
|
239
|
|
240 The reply form of the HTTP 1.0 protocol again has three parts:
|
|
241
|
|
242 1. One line giving the response code
|
|
243 2. An optional set of RFC-822-style headers
|
|
244 3. The data
|
|
245
|
|
246 Again, the headers and data are separated by a blank line.
|
|
247
|
|
248 The response code line has the form
|
|
249
|
|
250 <version> <responsecode> <responsestring>
|
|
251
|
|
252 where <version> is the protocol version (always "HTTP/1.0"),
|
|
253 <responsecode> is a 3-digit response code indicating success or
|
|
254 failure of the request, and <responsestring> is an optional
|
|
255 human-readable string explaining what the response code means.
|
|
256
|
|
257 This server parses the request and the headers, and then calls a
|
|
258 function specific to the request type (<command>). Specifically,
|
|
259 a request SPAM will be handled by a method do_SPAM(). If no
|
|
260 such method exists the server sends an error response to the
|
|
261 client. If it exists, it is called with no arguments:
|
|
262
|
|
263 do_SPAM()
|
|
264
|
|
265 Note that the request name is case sensitive (i.e. SPAM and spam
|
|
266 are different requests).
|
|
267
|
|
268 The various request details are stored in instance variables:
|
|
269
|
|
270 - client_address is the client IP address in the form (host,
|
|
271 port);
|
|
272
|
|
273 - command, path and version are the broken-down request line;
|
|
274
|
|
275 - headers is an instance of mimetools.Message (or a derived
|
|
276 class) containing the header information;
|
|
277
|
|
278 - rfile is a file object open for reading positioned at the
|
|
279 start of the optional input data part;
|
|
280
|
|
281 - wfile is a file object open for writing.
|
|
282
|
|
283 IT IS IMPORTANT TO ADHERE TO THE PROTOCOL FOR WRITING!
|
|
284
|
|
285 The first thing to be written must be the response line. Then
|
|
286 follow 0 or more header lines, then a blank line, and then the
|
|
287 actual data (if any). The meaning of the header lines depends on
|
|
288 the command executed by the server; in most cases, when data is
|
|
289 returned, there should be at least one header line of the form
|
|
290
|
|
291 Content-type: <type>/<subtype>
|
|
292
|
|
293 where <type> and <subtype> should be registered MIME types,
|
|
294 e.g. "text/html" or "text/plain".
|
|
295
|
|
296 """
|
|
297
|
|
298 # The Python system version, truncated to its first component.
|
|
299 sys_version = "Python/" + sys.version.split()[0]
|
|
300
|
|
301 # The server software version. You may want to override this.
|
|
302 # The format is multiple whitespace-separated strings,
|
|
303 # where each string is of the form name[/version].
|
|
304 server_version = "BaseHTTP/" + __version__
|
|
305
|
|
306 def parse_request(self):
|
|
307 """Parse a request (internal).
|
|
308
|
|
309 The request should be stored in self.raw_request; the results
|
|
310 are in self.command, self.path, self.request_version and
|
|
311 self.headers.
|
|
312
|
|
313 Return value is 1 for success, 0 for failure; on failure, an
|
|
314 error is sent back.
|
|
315
|
|
316 """
|
|
317 self.request_version = version = "HTTP/0.9" # Default
|
|
318 requestline = self.raw_requestline
|
|
319 if requestline[-2:] == '\r\n':
|
|
320 requestline = requestline[:-2]
|
|
321 elif requestline[-1:] == '\n':
|
|
322 requestline = requestline[:-1]
|
|
323 self.requestline = requestline
|
|
324 words = requestline.split()
|
|
325 if len(words) == 3:
|
|
326 [command, path, version] = words
|
|
327 if version[:5] != 'HTTP/':
|
|
328 self.send_error(400, "Bad request version (%s)" % `version`)
|
|
329 return 0
|
|
330 elif len(words) == 2:
|
|
331 [command, path] = words
|
|
332 if command != 'GET':
|
|
333 self.send_error(400,
|
|
334 "Bad HTTP/0.9 request type (%s)" % `command`)
|
|
335 return 0
|
|
336 else:
|
|
337 self.send_error(400, "Bad request syntax (%s)" % `requestline`)
|
|
338 return 0
|
|
339 self.command, self.path, self.request_version = command, path, version
|
|
340 self.headers = self.MessageClass(self.rfile, 0)
|
|
341 return 1
|
|
342
|
|
343 def handle(self):
|
|
344 """Handle a single HTTP request.
|
|
345
|
|
346 You normally don't need to override this method; see the class
|
|
347 __doc__ string for information on how to handle specific HTTP
|
|
348 commands such as GET and POST.
|
|
349
|
|
350 """
|
|
351
|
|
352 self.raw_requestline = self.rfile.readline()
|
|
353 if not self.parse_request(): # An error code has been sent, just exit
|
|
354 return
|
|
355 mname = 'do_' + self.command
|
|
356 if not hasattr(self, mname):
|
|
357 self.send_error(501, "Unsupported method (%s)" % `self.command`)
|
|
358 return
|
|
359 method = getattr(self, mname)
|
|
360 method()
|
|
361
|
|
362 def send_error(self, code, message=None):
|
|
363 """Send and log an error reply.
|
|
364
|
|
365 Arguments are the error code, and a detailed message.
|
|
366 The detailed message defaults to the short entry matching the
|
|
367 response code.
|
|
368
|
|
369 This sends an error response (so it must be called before any
|
|
370 output has been generated), logs the error, and finally sends
|
|
371 a piece of HTML explaining the error to the user.
|
|
372
|
|
373 """
|
|
374
|
|
375 try:
|
|
376 short, long = self.responses[code]
|
|
377 except KeyError:
|
|
378 short, long = '???', '???'
|
|
379 if not message:
|
|
380 message = short
|
|
381 explain = long
|
|
382 self.log_error("code %d, message %s", code, message)
|
|
383 self.send_response(code, message)
|
|
384 self.send_header("Content-Type", "text/html")
|
|
385 self.end_headers()
|
|
386 self.wfile.write(self.error_message_format %
|
|
387 {'code': code,
|
|
388 'message': message,
|
|
389 'explain': explain})
|
|
390
|
|
391 error_message_format = DEFAULT_ERROR_MESSAGE
|
|
392
|
|
393 def send_response(self, code, message=None):
|
|
394 """Send the response header and log the response code.
|
|
395
|
|
396 Also send two standard headers with the server software
|
|
397 version and the current date.
|
|
398
|
|
399 """
|
|
400 self.log_request(code)
|
|
401 if message is None:
|
|
402 if self.responses.has_key(code):
|
|
403 message = self.responses[code][0]
|
|
404 else:
|
|
405 message = ''
|
|
406 if self.request_version != 'HTTP/0.9':
|
|
407 self.wfile.write("%s %s %s\r\n" %
|
|
408 (self.protocol_version, str(code), message))
|
|
409 self.send_header('Server', self.version_string())
|
|
410 self.send_header('Date', self.date_time_string())
|
|
411
|
|
412 def send_header(self, keyword, value):
|
|
413 """Send a MIME header."""
|
|
414 if self.request_version != 'HTTP/0.9':
|
|
415 self.wfile.write("%s: %s\r\n" % (keyword, value))
|
|
416
|
|
417 def end_headers(self):
|
|
418 """Send the blank line ending the MIME headers."""
|
|
419 if self.request_version != 'HTTP/0.9':
|
|
420 self.wfile.write("\r\n")
|
|
421
|
|
422 def log_request(self, code='-', size='-'):
|
|
423 """Log an accepted request.
|
|
424
|
|
425 This is called by send_reponse().
|
|
426
|
|
427 """
|
|
428
|
|
429 self.log_message('"%s" %s %s',
|
|
430 self.requestline, str(code), str(size))
|
|
431
|
|
432 def log_error(self, *args):
|
|
433 """Log an error.
|
|
434
|
|
435 This is called when a request cannot be fulfilled. By
|
|
436 default it passes the message on to log_message().
|
|
437
|
|
438 Arguments are the same as for log_message().
|
|
439
|
|
440 XXX This should go to the separate error log.
|
|
441
|
|
442 """
|
|
443
|
|
444 apply(self.log_message, args)
|
|
445
|
|
446 def log_message(self, format, *args):
|
|
447 """Log an arbitrary message.
|
|
448
|
|
449 This is used by all other logging functions. Override
|
|
450 it if you have specific logging wishes.
|
|
451
|
|
452 The first argument, FORMAT, is a format string for the
|
|
453 message to be logged. If the format string contains
|
|
454 any % escapes requiring parameters, they should be
|
|
455 specified as subsequent arguments (it's just like
|
|
456 printf!).
|
|
457
|
|
458 The client host and current date/time are prefixed to
|
|
459 every message.
|
|
460
|
|
461 """
|
|
462
|
|
463 sys.stderr.write("%s - - [%s] %s\n" %
|
|
464 (self.address_string(),
|
|
465 self.log_date_time_string(),
|
|
466 format%args))
|
|
467
|
|
468 def version_string(self):
|
|
469 """Return the server software version string."""
|
|
470 return self.server_version + ' ' + self.sys_version
|
|
471
|
|
472 def date_time_string(self):
|
|
473 """Return the current date and time formatted for a message header."""
|
|
474 now = time.time()
|
|
475 year, month, day, hh, mm, ss, wd, y, z = time.gmtime(now)
|
|
476 s = "%s, %02d %3s %4d %02d:%02d:%02d GMT" % (
|
|
477 self.weekdayname[wd],
|
|
478 day, self.monthname[month], year,
|
|
479 hh, mm, ss)
|
|
480 return s
|
|
481
|
|
482 def log_date_time_string(self):
|
|
483 """Return the current time formatted for logging."""
|
|
484 now = time.time()
|
|
485 year, month, day, hh, mm, ss, x, y, z = time.localtime(now)
|
|
486 s = "%02d/%3s/%04d %02d:%02d:%02d" % (
|
|
487 day, self.monthname[month], year, hh, mm, ss)
|
|
488 return s
|
|
489
|
|
490 weekdayname = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
|
|
491
|
|
492 monthname = [None,
|
|
493 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
|
|
494 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
|
|
495
|
|
496 def address_string(self):
|
|
497 """Return the client address formatted for logging.
|
|
498
|
|
499 This version looks up the full hostname using gethostbyaddr(),
|
|
500 and tries to find a name that contains at least one dot.
|
|
501
|
|
502 """
|
|
503
|
|
504 host, port = self.client_address
|
|
505 return socket.getfqdn(host)
|
|
506
|
|
507 # Essentially static class variables
|
|
508
|
|
509 # The version of the HTTP protocol we support.
|
|
510 # Don't override unless you know what you're doing (hint: incoming
|
|
511 # requests are required to have exactly this version string).
|
|
512 protocol_version = "HTTP/1.0"
|
|
513
|
|
514 # The Message-like class used to parse headers
|
|
515 MessageClass = mimetools.Message
|
|
516
|
|
517 # Table mapping response codes to messages; entries have the
|
|
518 # form {code: (shortmessage, longmessage)}.
|
|
519 # See http://www.w3.org/hypertext/WWW/Protocols/HTTP/HTRESP.html
|
|
520 responses = {
|
|
521 200: ('OK', 'Request fulfilled, document follows'),
|
|
522 201: ('Created', 'Document created, URL follows'),
|
|
523 202: ('Accepted',
|
|
524 'Request accepted, processing continues off-line'),
|
|
525 203: ('Partial information', 'Request fulfilled from cache'),
|
|
526 204: ('No response', 'Request fulfilled, nothing follows'),
|
|
527
|
|
528 301: ('Moved', 'Object moved permanently -- see URI list'),
|
|
529 302: ('Found', 'Object moved temporarily -- see URI list'),
|
|
530 303: ('Method', 'Object moved -- see Method and URL list'),
|
|
531 304: ('Not modified',
|
|
532 'Document has not changed singe given time'),
|
|
533
|
|
534 400: ('Bad request',
|
|
535 'Bad request syntax or unsupported method'),
|
|
536 401: ('Unauthorized',
|
|
537 'No permission -- see authorization schemes'),
|
|
538 402: ('Payment required',
|
|
539 'No payment -- see charging schemes'),
|
|
540 403: ('Forbidden',
|
|
541 'Request forbidden -- authorization will not help'),
|
|
542 404: ('Not found', 'Nothing matches the given URI'),
|
|
543
|
|
544 500: ('Internal error', 'Server got itself in trouble'),
|
|
545 501: ('Not implemented',
|
|
546 'Server does not support this operation'),
|
|
547 502: ('Service temporarily overloaded',
|
|
548 'The server cannot process the request due to a high load'),
|
|
549 503: ('Gateway timeout',
|
|
550 'The gateway server did not receive a timely response'),
|
|
551
|
|
552 }
|
|
553
|
|
554
|
|
555 def test(HandlerClass = BaseHTTPRequestHandler,
|
|
556 ServerClass = HTTPServer):
|
|
557 """Test the HTTP request handler class.
|
|
558
|
|
559 This runs an HTTP server on port 8000 (or the first command line
|
|
560 argument).
|
|
561
|
|
562 """
|
|
563
|
|
564 if sys.argv[1:]:
|
|
565 port = int(sys.argv[1])
|
|
566 else:
|
|
567 port = 8000
|
|
568 server_address = ('', port)
|
|
569
|
|
570 httpd = ServerClass(server_address, HandlerClass)
|
|
571
|
|
572 sa = httpd.socket.getsockname()
|
|
573 print "Serving HTTP on", sa[0], "port", sa[1], "..."
|
|
574 httpd.serve_forever()
|
|
575
|
|
576
|
|
577 if __name__ == '__main__':
|
|
578 test()
|
105377
|
579
|
|
580 # arch-tag: 567449b3-cc90-45b6-bbe3-1e113995bdae
|