Commit 548703a1 authored by Guido van Rossum's avatar Guido van Rossum

The usual.

parent 65e53990
...@@ -89,19 +89,19 @@ DEFAULT_ERROR_MESSAGE = """\ ...@@ -89,19 +89,19 @@ DEFAULT_ERROR_MESSAGE = """\
class HTTPServer(SocketServer.TCPServer): class HTTPServer(SocketServer.TCPServer):
def server_bind(self): def server_bind(self):
"""Override server_bind to store the server name.""" """Override server_bind to store the server name."""
SocketServer.TCPServer.server_bind(self) SocketServer.TCPServer.server_bind(self)
host, port = self.socket.getsockname() host, port = self.socket.getsockname()
if not host or host == '0.0.0.0': if not host or host == '0.0.0.0':
host = socket.gethostname() host = socket.gethostname()
hostname, hostnames, hostaddrs = socket.gethostbyaddr(host) hostname, hostnames, hostaddrs = socket.gethostbyaddr(host)
if '.' not in hostname: if '.' not in hostname:
for host in hostnames: for host in hostnames:
if '.' in host: if '.' in host:
hostname = host hostname = host
break break
self.server_name = hostname self.server_name = hostname
self.server_port = port self.server_port = port
class BaseHTTPRequestHandler(SocketServer.StreamRequestHandler): class BaseHTTPRequestHandler(SocketServer.StreamRequestHandler):
...@@ -217,196 +217,196 @@ class BaseHTTPRequestHandler(SocketServer.StreamRequestHandler): ...@@ -217,196 +217,196 @@ class BaseHTTPRequestHandler(SocketServer.StreamRequestHandler):
server_version = "BaseHTTP/" + __version__ server_version = "BaseHTTP/" + __version__
def handle(self): def handle(self):
"""Handle a single HTTP request. """Handle a single HTTP request.
You normally don't need to override this method; see the class You normally don't need to override this method; see the class
__doc__ string for information on how to handle specific HTTP __doc__ string for information on how to handle specific HTTP
commands such as GET and POST. commands such as GET and POST.
""" """
self.raw_requestline = self.rfile.readline() self.raw_requestline = self.rfile.readline()
self.request_version = version = "HTTP/0.9" # Default self.request_version = version = "HTTP/0.9" # Default
requestline = self.raw_requestline requestline = self.raw_requestline
if requestline[-2:] == '\r\n': if requestline[-2:] == '\r\n':
requestline = requestline[:-2] requestline = requestline[:-2]
elif requestline[-1:] == '\n': elif requestline[-1:] == '\n':
requestline = requestline[:-1] requestline = requestline[:-1]
self.requestline = requestline self.requestline = requestline
words = string.split(requestline) words = string.split(requestline)
if len(words) == 3: if len(words) == 3:
[command, path, version] = words [command, path, version] = words
if version[:5] != 'HTTP/': if version[:5] != 'HTTP/':
self.send_error(400, "Bad request version (%s)" % `version`) self.send_error(400, "Bad request version (%s)" % `version`)
return return
elif len(words) == 2: elif len(words) == 2:
[command, path] = words [command, path] = words
if command != 'GET': if command != 'GET':
self.send_error(400, self.send_error(400,
"Bad HTTP/0.9 request type (%s)" % `command`) "Bad HTTP/0.9 request type (%s)" % `command`)
return return
else: else:
self.send_error(400, "Bad request syntax (%s)" % `requestline`) self.send_error(400, "Bad request syntax (%s)" % `requestline`)
return return
self.command, self.path, self.request_version = command, path, version self.command, self.path, self.request_version = command, path, version
self.headers = self.MessageClass(self.rfile, 0) self.headers = self.MessageClass(self.rfile, 0)
mname = 'do_' + command mname = 'do_' + command
if not hasattr(self, mname): if not hasattr(self, mname):
self.send_error(501, "Unsupported method (%s)" % `mname`) self.send_error(501, "Unsupported method (%s)" % `mname`)
return return
method = getattr(self, mname) method = getattr(self, mname)
method() method()
def send_error(self, code, message=None): def send_error(self, code, message=None):
"""Send and log an error reply. """Send and log an error reply.
Arguments are the error code, and a detailed message. Arguments are the error code, and a detailed message.
The detailed message defaults to the short entry matching the The detailed message defaults to the short entry matching the
response code. response code.
This sends an error response (so it must be called before any This sends an error response (so it must be called before any
output has been generated), logs the error, and finally sends output has been generated), logs the error, and finally sends
a piece of HTML explaining the error to the user. a piece of HTML explaining the error to the user.
""" """
try: try:
short, long = self.responses[code] short, long = self.responses[code]
except KeyError: except KeyError:
short, long = '???', '???' short, long = '???', '???'
if not message: if not message:
message = short message = short
explain = long explain = long
self.log_error("code %d, message %s", code, message) self.log_error("code %d, message %s", code, message)
self.send_response(code, message) self.send_response(code, message)
self.end_headers() self.end_headers()
self.wfile.write(self.error_message_format % self.wfile.write(self.error_message_format %
{'code': code, {'code': code,
'message': message, 'message': message,
'explain': explain}) 'explain': explain})
error_message_format = DEFAULT_ERROR_MESSAGE error_message_format = DEFAULT_ERROR_MESSAGE
def send_response(self, code, message=None): def send_response(self, code, message=None):
"""Send the response header and log the response code. """Send the response header and log the response code.
Also send two standard headers with the server software Also send two standard headers with the server software
version and the current date. version and the current date.
""" """
self.log_request(code) self.log_request(code)
if message is None: if message is None:
if self.responses.has_key(code): if self.responses.has_key(code):
message = self.responses[code][0] message = self.responses[code][0]
else: else:
message = '' message = ''
if self.request_version != 'HTTP/0.9': if self.request_version != 'HTTP/0.9':
self.wfile.write("%s %s %s\r\n" % self.wfile.write("%s %s %s\r\n" %
(self.protocol_version, str(code), message)) (self.protocol_version, str(code), message))
self.send_header('Server', self.version_string()) self.send_header('Server', self.version_string())
self.send_header('Date', self.date_time_string()) self.send_header('Date', self.date_time_string())
def send_header(self, keyword, value): def send_header(self, keyword, value):
"""Send a MIME header.""" """Send a MIME header."""
if self.request_version != 'HTTP/0.9': if self.request_version != 'HTTP/0.9':
self.wfile.write("%s: %s\r\n" % (keyword, value)) self.wfile.write("%s: %s\r\n" % (keyword, value))
def end_headers(self): def end_headers(self):
"""Send the blank line ending the MIME headers.""" """Send the blank line ending the MIME headers."""
if self.request_version != 'HTTP/0.9': if self.request_version != 'HTTP/0.9':
self.wfile.write("\r\n") self.wfile.write("\r\n")
def log_request(self, code='-', size='-'): def log_request(self, code='-', size='-'):
"""Log an accepted request. """Log an accepted request.
This is called by send_reponse(). This is called by send_reponse().
""" """
self.log_message('"%s" %s %s', self.log_message('"%s" %s %s',
self.requestline, str(code), str(size)) self.requestline, str(code), str(size))
def log_error(self, *args): def log_error(self, *args):
"""Log an error. """Log an error.
This is called when a request cannot be fulfilled. By This is called when a request cannot be fulfilled. By
default it passes the message on to log_message(). default it passes the message on to log_message().
Arguments are the same as for log_message(). Arguments are the same as for log_message().
XXX This should go to the separate error log. XXX This should go to the separate error log.
""" """
apply(self.log_message, args) apply(self.log_message, args)
def log_message(self, format, *args): def log_message(self, format, *args):
"""Log an arbitrary message. """Log an arbitrary message.
This is used by all other logging functions. Override This is used by all other logging functions. Override
it if you have specific logging wishes. it if you have specific logging wishes.
The first argument, FORMAT, is a format string for the The first argument, FORMAT, is a format string for the
message to be logged. If the format string contains message to be logged. If the format string contains
any % escapes requiring parameters, they should be any % escapes requiring parameters, they should be
specified as subsequent arguments (it's just like specified as subsequent arguments (it's just like
printf!). printf!).
The client host and current date/time are prefixed to The client host and current date/time are prefixed to
every message. every message.
""" """
sys.stderr.write("%s - - [%s] %s\n" % sys.stderr.write("%s - - [%s] %s\n" %
(self.address_string(), (self.address_string(),
self.log_date_time_string(), self.log_date_time_string(),
format%args)) format%args))
def version_string(self): def version_string(self):
"""Return the server software version string.""" """Return the server software version string."""
return self.server_version + ' ' + self.sys_version return self.server_version + ' ' + self.sys_version
def date_time_string(self): def date_time_string(self):
"""Return the current date and time formatted for a message header.""" """Return the current date and time formatted for a message header."""
now = time.time() now = time.time()
year, month, day, hh, mm, ss, wd, y, z = time.gmtime(now) year, month, day, hh, mm, ss, wd, y, z = time.gmtime(now)
s = "%s, %02d %3s %4d %02d:%02d:%02d GMT" % ( s = "%s, %02d %3s %4d %02d:%02d:%02d GMT" % (
self.weekdayname[wd], self.weekdayname[wd],
day, self.monthname[month], year, day, self.monthname[month], year,
hh, mm, ss) hh, mm, ss)
return s return s
def log_date_time_string(self): def log_date_time_string(self):
"""Return the current time formatted for logging.""" """Return the current time formatted for logging."""
now = time.time() now = time.time()
year, month, day, hh, mm, ss, x, y, z = time.localtime(now) year, month, day, hh, mm, ss, x, y, z = time.localtime(now)
s = "%02d/%3s/%04d %02d:%02d:%02d" % ( s = "%02d/%3s/%04d %02d:%02d:%02d" % (
day, self.monthname[month], year, hh, mm, ss) day, self.monthname[month], year, hh, mm, ss)
return s return s
weekdayname = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] weekdayname = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
monthname = [None, monthname = [None,
'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
def address_string(self): def address_string(self):
"""Return the client address formatted for logging. """Return the client address formatted for logging.
This version looks up the full hostname using gethostbyaddr(), This version looks up the full hostname using gethostbyaddr(),
and tries to find a name that contains at least one dot. and tries to find a name that contains at least one dot.
""" """
(host, port) = self.client_address (host, port) = self.client_address
try: try:
name, names, addresses = socket.gethostbyaddr(host) name, names, addresses = socket.gethostbyaddr(host)
except socket.error, msg: except socket.error, msg:
return host return host
names.insert(0, name) names.insert(0, name)
for name in names: for name in names:
if '.' in name: return name if '.' in name: return name
return names[0] return names[0]
# Essentially static class variables # Essentially static class variables
...@@ -423,42 +423,42 @@ class BaseHTTPRequestHandler(SocketServer.StreamRequestHandler): ...@@ -423,42 +423,42 @@ class BaseHTTPRequestHandler(SocketServer.StreamRequestHandler):
# form {code: (shortmessage, longmessage)}. # form {code: (shortmessage, longmessage)}.
# See http://www.w3.org/hypertext/WWW/Protocols/HTTP/HTRESP.html # See http://www.w3.org/hypertext/WWW/Protocols/HTTP/HTRESP.html
responses = { responses = {
200: ('OK', 'Request fulfilled, document follows'), 200: ('OK', 'Request fulfilled, document follows'),
201: ('Created', 'Document created, URL follows'), 201: ('Created', 'Document created, URL follows'),
202: ('Accepted', 202: ('Accepted',
'Request accepted, processing continues off-line'), 'Request accepted, processing continues off-line'),
203: ('Partial information', 'Request fulfilled from cache'), 203: ('Partial information', 'Request fulfilled from cache'),
204: ('No response', 'Request fulfilled, nothing follows'), 204: ('No response', 'Request fulfilled, nothing follows'),
301: ('Moved', 'Object moved permanently -- see URI list'), 301: ('Moved', 'Object moved permanently -- see URI list'),
302: ('Found', 'Object moved temporarily -- see URI list'), 302: ('Found', 'Object moved temporarily -- see URI list'),
303: ('Method', 'Object moved -- see Method and URL list'), 303: ('Method', 'Object moved -- see Method and URL list'),
304: ('Not modified', 304: ('Not modified',
'Document has not changed singe given time'), 'Document has not changed singe given time'),
400: ('Bad request', 400: ('Bad request',
'Bad request syntax or unsupported method'), 'Bad request syntax or unsupported method'),
401: ('Unauthorized', 401: ('Unauthorized',
'No permission -- see authorization schemes'), 'No permission -- see authorization schemes'),
402: ('Payment required', 402: ('Payment required',
'No payment -- see charging schemes'), 'No payment -- see charging schemes'),
403: ('Forbidden', 403: ('Forbidden',
'Request forbidden -- authorization will not help'), 'Request forbidden -- authorization will not help'),
404: ('Not found', 'Nothing matches the given URI'), 404: ('Not found', 'Nothing matches the given URI'),
500: ('Internal error', 'Server got itself in trouble'), 500: ('Internal error', 'Server got itself in trouble'),
501: ('Not implemented', 501: ('Not implemented',
'Server does not support this operation'), 'Server does not support this operation'),
502: ('Service temporarily overloaded', 502: ('Service temporarily overloaded',
'The server cannot process the request due to a high load'), 'The server cannot process the request due to a high load'),
503: ('Gateway timeout', 503: ('Gateway timeout',
'The gateway server did not receive a timely response'), 'The gateway server did not receive a timely response'),
} }
def test(HandlerClass = BaseHTTPRequestHandler, def test(HandlerClass = BaseHTTPRequestHandler,
ServerClass = HTTPServer): ServerClass = HTTPServer):
"""Test the HTTP request handler class. """Test the HTTP request handler class.
This runs an HTTP server on port 8000 (or the first command line This runs an HTTP server on port 8000 (or the first command line
...@@ -467,9 +467,9 @@ def test(HandlerClass = BaseHTTPRequestHandler, ...@@ -467,9 +467,9 @@ def test(HandlerClass = BaseHTTPRequestHandler,
""" """
if sys.argv[1:]: if sys.argv[1:]:
port = string.atoi(sys.argv[1]) port = string.atoi(sys.argv[1])
else: else:
port = 8000 port = 8000
server_address = ('', port) server_address = ('', port)
httpd = ServerClass(server_address, HandlerClass) httpd = ServerClass(server_address, HandlerClass)
......
...@@ -41,47 +41,47 @@ class BastionClass: ...@@ -41,47 +41,47 @@ class BastionClass:
""" """
def __init__(self, get, name): def __init__(self, get, name):
"""Constructor. """Constructor.
Arguments: Arguments:
get - a function that gets the attribute value (by name) get - a function that gets the attribute value (by name)
name - a human-readable name for the original object name - a human-readable name for the original object
(suggestion: use repr(object)) (suggestion: use repr(object))
""" """
self._get_ = get self._get_ = get
self._name_ = name self._name_ = name
def __repr__(self): def __repr__(self):
"""Return a representation string. """Return a representation string.
This includes the name passed in to the constructor, so that This includes the name passed in to the constructor, so that
if you print the bastion during debugging, at least you have if you print the bastion during debugging, at least you have
some idea of what it is. some idea of what it is.
""" """
return "<Bastion for %s>" % self._name_ return "<Bastion for %s>" % self._name_
def __getattr__(self, name): def __getattr__(self, name):
"""Get an as-yet undefined attribute value. """Get an as-yet undefined attribute value.
This calls the get() function that was passed to the This calls the get() function that was passed to the
constructor. The result is stored as an instance variable so constructor. The result is stored as an instance variable so
that the next time the same attribute is requested, that the next time the same attribute is requested,
__getattr__() won't be invoked. __getattr__() won't be invoked.
If the get() function raises an exception, this is simply If the get() function raises an exception, this is simply
passed on -- exceptions are not cached. passed on -- exceptions are not cached.
""" """
attribute = self._get_(name) attribute = self._get_(name)
self.__dict__[name] = attribute self.__dict__[name] = attribute
return attribute return attribute
def Bastion(object, filter = lambda name: name[:1] != '_', def Bastion(object, filter = lambda name: name[:1] != '_',
name=None, bastionclass=BastionClass): name=None, bastionclass=BastionClass):
"""Create a bastion for an object, using an optional filter. """Create a bastion for an object, using an optional filter.
See the Bastion module's documentation for background. See the Bastion module's documentation for background.
...@@ -109,33 +109,33 @@ def Bastion(object, filter = lambda name: name[:1] != '_', ...@@ -109,33 +109,33 @@ def Bastion(object, filter = lambda name: name[:1] != '_',
# the user has full access to all instance variables! # the user has full access to all instance variables!
def get1(name, object=object, filter=filter): def get1(name, object=object, filter=filter):
"""Internal function for Bastion(). See source comments.""" """Internal function for Bastion(). See source comments."""
if filter(name): if filter(name):
attribute = getattr(object, name) attribute = getattr(object, name)
if type(attribute) == MethodType: if type(attribute) == MethodType:
return attribute return attribute
raise AttributeError, name raise AttributeError, name
def get2(name, get1=get1): def get2(name, get1=get1):
"""Internal function for Bastion(). See source comments.""" """Internal function for Bastion(). See source comments."""
return get1(name) return get1(name)
if name is None: if name is None:
name = `object` name = `object`
return bastionclass(get2, name) return bastionclass(get2, name)
def _test(): def _test():
"""Test the Bastion() function.""" """Test the Bastion() function."""
class Original: class Original:
def __init__(self): def __init__(self):
self.sum = 0 self.sum = 0
def add(self, n): def add(self, n):
self._add(n) self._add(n)
def _add(self, n): def _add(self, n):
self.sum = self.sum + n self.sum = self.sum + n
def total(self): def total(self):
return self.sum return self.sum
o = Original() o = Original()
b = Bastion(o) b = Bastion(o)
testcode = """if 1: testcode = """if 1:
...@@ -143,23 +143,23 @@ def _test(): ...@@ -143,23 +143,23 @@ def _test():
b.add(18) b.add(18)
print "b.total() =", b.total() print "b.total() =", b.total()
try: try:
print "b.sum =", b.sum, print "b.sum =", b.sum,
except: except:
print "inaccessible" print "inaccessible"
else: else:
print "accessible" print "accessible"
try: try:
print "b._add =", b._add, print "b._add =", b._add,
except: except:
print "inaccessible" print "inaccessible"
else: else:
print "accessible" print "accessible"
try: try:
print "b._get_.func_defaults =", b._get_.func_defaults, print "b._get_.func_defaults =", b._get_.func_defaults,
except: except:
print "inaccessible" print "inaccessible"
else: else:
print "accessible" print "accessible"
\n""" \n"""
exec testcode exec testcode
print '='*20, "Using rexec:", '='*20 print '='*20, "Using rexec:", '='*20
......
...@@ -30,138 +30,138 @@ class CGIHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): ...@@ -30,138 +30,138 @@ class CGIHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
""" """
def do_POST(self): def do_POST(self):
"""Serve a POST request. """Serve a POST request.
This is only implemented for CGI scripts. This is only implemented for CGI scripts.
""" """
if self.is_cgi(): if self.is_cgi():
self.run_cgi() self.run_cgi()
else: else:
self.send_error(501, "Can only POST to CGI scripts") self.send_error(501, "Can only POST to CGI scripts")
def send_head(self): def send_head(self):
"""Version of send_head that support CGI scripts""" """Version of send_head that support CGI scripts"""
if self.is_cgi(): if self.is_cgi():
return self.run_cgi() return self.run_cgi()
else: else:
return SimpleHTTPServer.SimpleHTTPRequestHandler.send_head(self) return SimpleHTTPServer.SimpleHTTPRequestHandler.send_head(self)
def is_cgi(self): def is_cgi(self):
"""test whether PATH corresponds to a CGI script. """test whether PATH corresponds to a CGI script.
Return a tuple (dir, rest) if PATH requires running a Return a tuple (dir, rest) if PATH requires running a
CGI script, None if not. Note that rest begins with a CGI script, None if not. Note that rest begins with a
slash if it is not empty. slash if it is not empty.
The default implementation tests whether the path The default implementation tests whether the path
begins with one of the strings in the list begins with one of the strings in the list
self.cgi_directories (and the next character is a '/' self.cgi_directories (and the next character is a '/'
or the end of the string). or the end of the string).
""" """
path = self.path path = self.path
for x in self.cgi_directories: for x in self.cgi_directories:
i = len(x) i = len(x)
if path[:i] == x and (not path[i:] or path[i] == '/'): if path[:i] == x and (not path[i:] or path[i] == '/'):
self.cgi_info = path[:i], path[i+1:] self.cgi_info = path[:i], path[i+1:]
return 1 return 1
return 0 return 0
cgi_directories = ['/cgi-bin', '/htbin'] cgi_directories = ['/cgi-bin', '/htbin']
def run_cgi(self): def run_cgi(self):
"""Execute a CGI script.""" """Execute a CGI script."""
dir, rest = self.cgi_info dir, rest = self.cgi_info
i = string.rfind(rest, '?') i = string.rfind(rest, '?')
if i >= 0: if i >= 0:
rest, query = rest[:i], rest[i+1:] rest, query = rest[:i], rest[i+1:]
else: else:
query = '' query = ''
i = string.find(rest, '/') i = string.find(rest, '/')
if i >= 0: if i >= 0:
script, rest = rest[:i], rest[i:] script, rest = rest[:i], rest[i:]
else: else:
script, rest = rest, '' script, rest = rest, ''
scriptname = dir + '/' + script scriptname = dir + '/' + script
scriptfile = self.translate_path(scriptname) scriptfile = self.translate_path(scriptname)
if not os.path.exists(scriptfile): if not os.path.exists(scriptfile):
self.send_error(404, "No such CGI script (%s)" % `scriptname`) self.send_error(404, "No such CGI script (%s)" % `scriptname`)
return return
if not os.path.isfile(scriptfile): if not os.path.isfile(scriptfile):
self.send_error(403, "CGI script is not a plain file (%s)" % self.send_error(403, "CGI script is not a plain file (%s)" %
`scriptname`) `scriptname`)
return return
if not executable(scriptfile): if not executable(scriptfile):
self.send_error(403, "CGI script is not executable (%s)" % self.send_error(403, "CGI script is not executable (%s)" %
`scriptname`) `scriptname`)
return return
nobody = nobody_uid() nobody = nobody_uid()
self.send_response(200, "Script output follows") self.send_response(200, "Script output follows")
self.wfile.flush() # Always flush before forking self.wfile.flush() # Always flush before forking
pid = os.fork() pid = os.fork()
if pid != 0: if pid != 0:
# Parent # Parent
pid, sts = os.waitpid(pid, 0) pid, sts = os.waitpid(pid, 0)
if sts: if sts:
self.log_error("CGI script exit status x%x" % sts) self.log_error("CGI script exit status x%x" % sts)
return return
# Child # Child
try: try:
# Reference: http://hoohoo.ncsa.uiuc.edu/cgi/env.html # Reference: http://hoohoo.ncsa.uiuc.edu/cgi/env.html
# XXX Much of the following could be prepared ahead of time! # XXX Much of the following could be prepared ahead of time!
env = {} env = {}
env['SERVER_SOFTWARE'] = self.version_string() env['SERVER_SOFTWARE'] = self.version_string()
env['SERVER_NAME'] = self.server.server_name env['SERVER_NAME'] = self.server.server_name
env['GATEWAY_INTERFACE'] = 'CGI/1.1' env['GATEWAY_INTERFACE'] = 'CGI/1.1'
env['SERVER_PROTOCOL'] = self.protocol_version env['SERVER_PROTOCOL'] = self.protocol_version
env['SERVER_PORT'] = str(self.server.server_port) env['SERVER_PORT'] = str(self.server.server_port)
env['REQUEST_METHOD'] = self.command env['REQUEST_METHOD'] = self.command
uqrest = urllib.unquote(rest) uqrest = urllib.unquote(rest)
env['PATH_INFO'] = uqrest env['PATH_INFO'] = uqrest
env['PATH_TRANSLATED'] = self.translate_path(uqrest) env['PATH_TRANSLATED'] = self.translate_path(uqrest)
env['SCRIPT_NAME'] = scriptname env['SCRIPT_NAME'] = scriptname
if query: if query:
env['QUERY_STRING'] = query env['QUERY_STRING'] = query
host = self.address_string() host = self.address_string()
if host != self.client_address[0]: if host != self.client_address[0]:
env['REMOTE_HOST'] = host env['REMOTE_HOST'] = host
env['REMOTE_ADDR'] = self.client_address[0] env['REMOTE_ADDR'] = self.client_address[0]
# AUTH_TYPE # AUTH_TYPE
# REMOTE_USER # REMOTE_USER
# REMOTE_IDENT # REMOTE_IDENT
env['CONTENT_TYPE'] = self.headers.type env['CONTENT_TYPE'] = self.headers.type
length = self.headers.getheader('content-length') length = self.headers.getheader('content-length')
if length: if length:
env['CONTENT_LENGTH'] = length env['CONTENT_LENGTH'] = length
accept = [] accept = []
for line in self.headers.getallmatchingheaders('accept'): for line in self.headers.getallmatchingheaders('accept'):
if line[:1] in string.whitespace: if line[:1] in string.whitespace:
accept.append(string.strip(line)) accept.append(string.strip(line))
else: else:
accept = accept + string.split(line[7:]) accept = accept + string.split(line[7:])
env['HTTP_ACCEPT'] = string.joinfields(accept, ',') env['HTTP_ACCEPT'] = string.joinfields(accept, ',')
ua = self.headers.getheader('user-agent') ua = self.headers.getheader('user-agent')
if ua: if ua:
env['HTTP_USER_AGENT'] = ua env['HTTP_USER_AGENT'] = ua
# XXX Other HTTP_* headers # XXX Other HTTP_* headers
decoded_query = string.replace(query, '+', ' ') decoded_query = string.replace(query, '+', ' ')
try: try:
os.setuid(nobody) os.setuid(nobody)
except os.error: except os.error:
pass pass
os.dup2(self.rfile.fileno(), 0) os.dup2(self.rfile.fileno(), 0)
os.dup2(self.wfile.fileno(), 1) os.dup2(self.wfile.fileno(), 1)
print scriptfile, script, decoded_query print scriptfile, script, decoded_query
os.execve(scriptfile, os.execve(scriptfile,
[script, decoded_query], [script, decoded_query],
env) env)
except: except:
self.server.handle_error(self.request, self.client_address) self.server.handle_error(self.request, self.client_address)
os._exit(127) os._exit(127)
nobody = None nobody = None
...@@ -170,26 +170,26 @@ def nobody_uid(): ...@@ -170,26 +170,26 @@ def nobody_uid():
"""Internal routine to get nobody's uid""" """Internal routine to get nobody's uid"""
global nobody global nobody
if nobody: if nobody:
return nobody return nobody
import pwd import pwd
try: try:
nobody = pwd.getpwnam('nobody')[2] nobody = pwd.getpwnam('nobody')[2]
except pwd.error: except pwd.error:
nobody = 1 + max(map(lambda x: x[2], pwd.getpwall())) nobody = 1 + max(map(lambda x: x[2], pwd.getpwall()))
return nobody return nobody
def executable(path): def executable(path):
"""Test for executable file.""" """Test for executable file."""
try: try:
st = os.stat(path) st = os.stat(path)
except os.error: except os.error:
return 0 return 0
return st[0] & 0111 != 0 return st[0] & 0111 != 0
def test(HandlerClass = CGIHTTPRequestHandler, def test(HandlerClass = CGIHTTPRequestHandler,
ServerClass = BaseHTTPServer.HTTPServer): ServerClass = BaseHTTPServer.HTTPServer):
SimpleHTTPServer.test(HandlerClass, ServerClass) SimpleHTTPServer.test(HandlerClass, ServerClass)
......
# Routines to force "compilation" of all .py files in a directory """Module/script to "compile" all .py files to .pyc (or .pyo) file.
# tree or on sys.path. By default recursion is pruned at a depth of
# 10 and the current directory, if it occurs in sys.path, is skipped. When called as a script with arguments, this compiles the directories
# When called as a script, compiles argument directories, or sys.path given as arguments recursively; the -l option prevents it from
# if no arguments. recursing into directories.
# After a similar module by Sjoerd Mullender.
Without arguments, if compiles all modules on sys.path, without
recursing into subdirectories. (Even though it should do so for
packages -- for now, you'll have to deal with packages separately.)
See module py_compile for details of the actual byte-compilation.
"""
import os import os
import sys import sys
import py_compile import py_compile
def compile_dir(dir, maxlevels = 10): def compile_dir(dir, maxlevels=10, ddir=None):
print 'Listing', dir, '...' """Byte-compile all modules in the given directory tree.
try:
names = os.listdir(dir) Arguments (only dir is required):
except os.error:
print "Can't list", dir dir: the directory to byte-compile
names = [] maxlevels: maximum recursion level (default 10)
names.sort() ddir: if given, purported directory name (this is the
for name in names: directory name that will show up in error messages)
fullname = os.path.join(dir, name)
if os.path.isfile(fullname): """
head, tail = name[:-3], name[-3:] print 'Listing', dir, '...'
if tail == '.py': try:
print 'Compiling', fullname, '...' names = os.listdir(dir)
try: except os.error:
py_compile.compile(fullname) print "Can't list", dir
except KeyboardInterrupt: names = []
del names[:] names.sort()
print '\n[interrupt]' for name in names:
break fullname = os.path.join(dir, name)
except: if ddir:
if type(sys.exc_type) == type(''): dfile = os.path.join(ddir, name)
exc_type_name = sys.exc_type else:
else: exc_type_name = sys.exc_type.__name__ dfile = None
print 'Sorry:', exc_type_name + ':', if os.path.isfile(fullname):
print sys.exc_value head, tail = name[:-3], name[-3:]
elif maxlevels > 0 and \ if tail == '.py':
name != os.curdir and name != os.pardir and \ print 'Compiling', fullname, '...'
os.path.isdir(fullname) and \ try:
not os.path.islink(fullname): py_compile.compile(fullname, None, dfile)
compile_dir(fullname, maxlevels - 1) except KeyboardInterrupt:
raise KeyboardInterrupt
except:
if type(sys.exc_type) == type(''):
exc_type_name = sys.exc_type
else: exc_type_name = sys.exc_type.__name__
print 'Sorry:', exc_type_name + ':',
print sys.exc_value
elif maxlevels > 0 and \
name != os.curdir and name != os.pardir and \
os.path.isdir(fullname) and \
not os.path.islink(fullname):
compile_dir(fullname, maxlevels - 1, dfile)
def compile_path(skip_curdir=1, maxlevels=0):
"""Byte-compile all module on sys.path.
Arguments (all optional):
skip_curdir: if true, skip current directory (default true)
maxlevels: max recursion level (default 0)
def compile_path(skip_curdir = 1): """
for dir in sys.path: for dir in sys.path:
if (not dir or dir == os.curdir) and skip_curdir: if (not dir or dir == os.curdir) and skip_curdir:
print 'Skipping current directory' print 'Skipping current directory'
else: else:
compile_dir(dir, 0) compile_dir(dir, maxlevels)
def main(): def main():
import getopt """Script main program."""
try: import getopt
opts, args = getopt.getopt(sys.argv[1:], 'l') try:
except getopt.error, msg: opts, args = getopt.getopt(sys.argv[1:], 'ld:')
print msg except getopt.error, msg:
print "usage: compileall [-l] [directory ...]" print msg
print "-l: don't recurse down" print "usage: compileall [-l] [-d destdir] [directory ...]"
print "if no arguments, -l sys.path is assumed" print "-l: don't recurse down"
maxlevels = 10 print "-d destdir: purported directory name for error messages"
for o, a in opts: print "if no arguments, -l sys.path is assumed"
if o == '-l': maxlevels = 0 sys.exit(2)
if args: maxlevels = 10
for dir in sys.argv[1:]: ddir = None
compile_dir(dir, maxlevels) for o, a in opts:
else: if o == '-l': maxlevels = 0
compile_path() if o == '-d': ddir = a
if ddir:
if len(args) != 1:
print "-d destdir require exactly one directory argument"
sys.exit(2)
try:
if args:
for dir in args:
compile_dir(dir, maxlevels, ddir)
else:
compile_path()
except KeyboardInterrupt:
print "\n[interrupt]"
if __name__ == '__main__': if __name__ == '__main__':
main() main()
...@@ -34,23 +34,23 @@ ConfigParser -- responsible for for parsing a list of ...@@ -34,23 +34,23 @@ ConfigParser -- responsible for for parsing a list of
sections() -- return all the configuration section names, sans DEFAULT sections() -- return all the configuration section names, sans DEFAULT
options(section) -- return list of configuration options for the named options(section) -- return list of configuration options for the named
section section
read(*filenames) -- read and parse the list of named configuration files read(*filenames) -- read and parse the list of named configuration files
get(section, option, raw=0) -- return a string value for the named get(section, option, raw=0) -- return a string value for the named
option. All % interpolations are option. All % interpolations are
expanded in the return values, based on expanded in the return values, based on
the defaults passed into the constructor the defaults passed into the constructor
and the DEFAULT section. and the DEFAULT section.
getint(section, options) -- like get(), but convert value to an integer getint(section, options) -- like get(), but convert value to an integer
getfloat(section, options) -- like get(), but convert value to a float getfloat(section, options) -- like get(), but convert value to a float
getboolean(section, options) -- like get(), but convert value to getboolean(section, options) -- like get(), but convert value to
a boolean (currently defined as 0 a boolean (currently defined as 0
or 1, only) or 1, only)
""" """
import sys import sys
...@@ -71,185 +71,186 @@ DEFAULTSECT = "DEFAULT" ...@@ -71,185 +71,186 @@ DEFAULTSECT = "DEFAULT"
# exception classes # exception classes
class Error: class Error:
def __init__(self, msg=''): def __init__(self, msg=''):
self.__msg = msg self.__msg = msg
def __repr__(self): def __repr__(self):
return self.__msg return self.__msg
class NoSectionError(Error): class NoSectionError(Error):
def __init__(self, section): def __init__(self, section):
Error.__init__(self, 'No section: %s' % section) Error.__init__(self, 'No section: %s' % section)
self.section = section self.section = section
class DuplicateSectionError(Error): class DuplicateSectionError(Error):
def __init__(self, section): def __init__(self, section):
Error.__init__(self, "Section %s already exists" % section) Error.__init__(self, "Section %s already exists" % section)
self.section = section self.section = section
class NoOptionError(Error): class NoOptionError(Error):
def __init__(self, option, section): def __init__(self, option, section):
Error.__init__(self, "No option `%s' in section: %s" % Error.__init__(self, "No option `%s' in section: %s" %
(option, section)) (option, section))
self.option = option self.option = option
self.section = section self.section = section
class InterpolationError(Error): class InterpolationError(Error):
def __init__(self, reference, option, section): def __init__(self, reference, option, section):
Error.__init__(self, Error.__init__(self,
"Bad value substitution: sect `%s', opt `%s', ref `%s'" "Bad value substitution: sect `%s', opt `%s', ref `%s'"
% (section, option, reference)) % (section, option, reference))
self.reference = reference self.reference = reference
self.option = option self.option = option
self.section = section self.section = section
class ConfigParser: class ConfigParser:
def __init__(self, defaults=None): def __init__(self, defaults=None):
self.__sections = {} self.__sections = {}
if defaults is None: if defaults is None:
self.__defaults = {} self.__defaults = {}
else: else:
self.__defaults = defaults self.__defaults = defaults
def defaults(self): def defaults(self):
return self.__defaults return self.__defaults
def sections(self): def sections(self):
"""Return a list of section names, excluding [DEFAULT]""" """Return a list of section names, excluding [DEFAULT]"""
# self.__sections will never have [DEFAULT] in it # self.__sections will never have [DEFAULT] in it
return self.__sections.keys() return self.__sections.keys()
def add_section(self, section): def add_section(self, section):
"""Create a new section in the configuration. """Create a new section in the configuration.
Raise DuplicateSectionError if a section by the specified name Raise DuplicateSectionError if a section by the specified name
already exists. already exists.
""" """
if self.__sections.has_key(section): if self.__sections.has_key(section):
raise DuplicateSectionError(section) raise DuplicateSectionError(section)
self.__sections[section] = {} self.__sections[section] = {}
def has_section(self, section): def has_section(self, section):
"""Indicate whether the named section is present in the configuration. """Indicate whether the named section is present in the configuration.
The DEFAULT section is not acknowledged. The DEFAULT section is not acknowledged.
""" """
return self.__sections.has_key(section) return self.__sections.has_key(section)
def options(self, section): def options(self, section):
try: try:
opts = self.__sections[section].copy() opts = self.__sections[section].copy()
except KeyError: except KeyError:
raise NoSectionError(section) raise NoSectionError(section)
opts.update(self.__defaults) opts.update(self.__defaults)
return opts.keys() return opts.keys()
def read(self, filenames): def read(self, filenames):
"""Read and parse a list of filenames.""" """Read and parse a list of filenames."""
if type(filenames) is type(''): if type(filenames) is type(''):
filenames = [filenames] filenames = [filenames]
for file in filenames: for file in filenames:
try: try:
fp = open(file, 'r') fp = open(file, 'r')
self.__read(fp) self.__read(fp)
except IOError: except IOError:
pass pass
def get(self, section, option, raw=0): def get(self, section, option, raw=0):
"""Get an option value for a given section. """Get an option value for a given section.
All % interpolations are expanded in the return values, based All % interpolations are expanded in the return values, based
on the defaults passed into the constructor. on the defaults passed into the constructor.
The section DEFAULT is special. The section DEFAULT is special.
""" """
try: try:
d = self.__sections[section].copy() sectdict = self.__sections[section].copy()
except KeyError: except KeyError:
if section == DEFAULTSECT: if section == DEFAULTSECT:
d = {} sectdict = {}
else: else:
raise NoSectionError(section) raise NoSectionError(section)
d.update(self.__defaults) d = self.__defaults.copy()
option = string.lower(option) d.update(sectdict)
try: option = string.lower(option)
rawval = d[option] try:
except KeyError: rawval = d[option]
raise NoOptionError(option, section) except KeyError:
# do the string interpolation raise NoOptionError(option, section)
if raw: # do the string interpolation
return rawval if raw:
try: return rawval
return rawval % d try:
except KeyError, key: return rawval % d
raise InterpolationError(key, option, section) except KeyError, key:
raise InterpolationError(key, option, section)
def __get(self, section, conv, option): def __get(self, section, conv, option):
return conv(self.get(section, option)) return conv(self.get(section, option))
def getint(self, section, option): def getint(self, section, option):
return self.__get(section, string.atoi, option) return self.__get(section, string.atoi, option)
def getfloat(self, section, option): def getfloat(self, section, option):
return self.__get(section, string.atof, option) return self.__get(section, string.atof, option)
def getboolean(self, section, option): def getboolean(self, section, option):
v = self.get(section, option) v = self.get(section, option)
val = string.atoi(v) val = string.atoi(v)
if val not in (0, 1): if val not in (0, 1):
raise ValueError, 'Not a boolean: %s' % v raise ValueError, 'Not a boolean: %s' % v
return val return val
def __read(self, fp): def __read(self, fp):
"""Parse a sectioned setup file. """Parse a sectioned setup file.
The sections in setup file contains a title line at the top, The sections in setup file contains a title line at the top,
indicated by a name in square brackets (`[]'), plus key/value indicated by a name in square brackets (`[]'), plus key/value
options lines, indicated by `name: value' format lines. options lines, indicated by `name: value' format lines.
Continuation are represented by an embedded newline then Continuation are represented by an embedded newline then
leading whitespace. Blank lines, lines beginning with a '#', leading whitespace. Blank lines, lines beginning with a '#',
and just about everything else is ignored. and just about everything else is ignored.
""" """
cursect = None # None, or a dictionary cursect = None # None, or a dictionary
optname = None optname = None
lineno = 0 lineno = 0
while 1: while 1:
line = fp.readline() line = fp.readline()
if not line: if not line:
break break
lineno = lineno + 1 lineno = lineno + 1
# comment or blank line? # comment or blank line?
if string.strip(line) == '' or line[0] in '#;': if string.strip(line) == '' or line[0] in '#;':
continue continue
if string.lower(string.split(line)[0]) == 'rem' \ if string.lower(string.split(line)[0]) == 'rem' \
and line[0] == "r": # no leading whitespace and line[0] == "r": # no leading whitespace
continue continue
# continuation line? # continuation line?
if line[0] in ' \t' and cursect <> None and optname: if line[0] in ' \t' and cursect <> None and optname:
value = string.strip(line) value = string.strip(line)
if value: if value:
cursect = cursect[optname] + '\n ' + value cursect = cursect[optname] + '\n ' + value
# a section header? # a section header?
elif secthead_cre.match(line) >= 0: elif secthead_cre.match(line) >= 0:
sectname = secthead_cre.group(1) sectname = secthead_cre.group(1)
if self.__sections.has_key(sectname): if self.__sections.has_key(sectname):
cursect = self.__sections[sectname] cursect = self.__sections[sectname]
elif sectname == DEFAULTSECT: elif sectname == DEFAULTSECT:
cursect = self.__defaults cursect = self.__defaults
else: else:
cursect = {'name': sectname} cursect = {'name': sectname}
self.__sections[sectname] = cursect self.__sections[sectname] = cursect
# So sections can't start with a continuation line. # So sections can't start with a continuation line.
optname = None optname = None
# an option line? # an option line?
elif option_cre.match(line) >= 0: elif option_cre.match(line) >= 0:
optname, optval = option_cre.group(1, 3) optname, optval = option_cre.group(1, 3)
optname = string.lower(optname) optname = string.lower(optname)
optval = string.strip(optval) optval = string.strip(optval)
# allow empty values # allow empty values
if optval == '""': if optval == '""':
optval = '' optval = ''
cursect[optname] = optval cursect[optname] = optval
# an error # an error
else: else:
print 'Error in %s at %d: %s', (fp.name, lineno, `line`) print 'Error in %s at %d: %s', (fp.name, lineno, `line`)
...@@ -48,18 +48,18 @@ Exception(*) ...@@ -48,18 +48,18 @@ Exception(*)
class Exception: class Exception:
def __init__(self, *args): def __init__(self, *args):
self.args = args self.args = args
def __str__(self): def __str__(self):
if not self.args: if not self.args:
return '' return ''
elif len(self.args) == 1: elif len(self.args) == 1:
return str(self.args[0]) return str(self.args[0])
else: else:
return str(self.args) return str(self.args)
def __getitem__(self, i): def __getitem__(self, i):
return self.args[i] return self.args[i]
class StandardError(Exception): class StandardError(Exception):
pass pass
...@@ -68,21 +68,21 @@ class SyntaxError(StandardError): ...@@ -68,21 +68,21 @@ class SyntaxError(StandardError):
filename = lineno = offset = text = None filename = lineno = offset = text = None
msg = "" msg = ""
def __init__(self, *args): def __init__(self, *args):
self.args = args self.args = args
if len(self.args) >= 1: if len(self.args) >= 1:
self.msg = self.args[0] self.msg = self.args[0]
if len(self.args) == 2: if len(self.args) == 2:
info = self.args[1] info = self.args[1]
try: try:
self.filename, self.lineno, self.offset, self.text = info self.filename, self.lineno, self.offset, self.text = info
except: except:
pass pass
def __str__(self): def __str__(self):
return str(self.msg) return str(self.msg)
class IOError(StandardError): class IOError(StandardError):
def __init__(self, *args): def __init__(self, *args):
self.args = args self.args = args
self.errno = None self.errno = None
self.strerror = None self.strerror = None
if len(args) == 2: if len(args) == 2:
...@@ -146,7 +146,7 @@ class MemoryError(StandardError): ...@@ -146,7 +146,7 @@ class MemoryError(StandardError):
class SystemExit(Exception): class SystemExit(Exception):
def __init__(self, *args): def __init__(self, *args):
self.args = args self.args = args
if len(args) == 0: if len(args) == 0:
self.code = None self.code = None
elif len(args) == 1: elif len(args) == 1:
......
...@@ -80,7 +80,7 @@ _state = None ...@@ -80,7 +80,7 @@ _state = None
def input(files=(), inplace=0, backup=""): def input(files=(), inplace=0, backup=""):
global _state global _state
if _state and _state._file: if _state and _state._file:
raise RuntimeError, "input() already active" raise RuntimeError, "input() already active"
_state = FileInput(files, inplace, backup) _state = FileInput(files, inplace, backup)
return _state return _state
...@@ -89,151 +89,151 @@ def close(): ...@@ -89,151 +89,151 @@ def close():
state = _state state = _state
_state = None _state = None
if state: if state:
state.close() state.close()
def nextfile(): def nextfile():
if not _state: if not _state:
raise RuntimeError, "no active input()" raise RuntimeError, "no active input()"
return _state.nextfile() return _state.nextfile()
def filename(): def filename():
if not _state: if not _state:
raise RuntimeError, "no active input()" raise RuntimeError, "no active input()"
return _state.filename() return _state.filename()
def lineno(): def lineno():
if not _state: if not _state:
raise RuntimeError, "no active input()" raise RuntimeError, "no active input()"
return _state.lineno() return _state.lineno()
def filelineno(): def filelineno():
if not _state: if not _state:
raise RuntimeError, "no active input()" raise RuntimeError, "no active input()"
return _state.filelineno() return _state.filelineno()
def isfirstline(): def isfirstline():
if not _state: if not _state:
raise RuntimeError, "no active input()" raise RuntimeError, "no active input()"
return _state.isfirstline() return _state.isfirstline()
def isstdin(): def isstdin():
if not _state: if not _state:
raise RuntimeError, "no active input()" raise RuntimeError, "no active input()"
return _state.isstdin() return _state.isstdin()
class FileInput: class FileInput:
def __init__(self, files=(), inplace=0, backup=""): def __init__(self, files=(), inplace=0, backup=""):
if type(files) == type(''): if type(files) == type(''):
files = (files,) files = (files,)
else: else:
files = tuple(files) files = tuple(files)
if not files: if not files:
files = tuple(sys.argv[1:]) files = tuple(sys.argv[1:])
if not files: if not files:
files = ('-',) files = ('-',)
self._files = files self._files = files
self._inplace = inplace self._inplace = inplace
self._backup = backup self._backup = backup
self._savestdout = None self._savestdout = None
self._output = None self._output = None
self._filename = None self._filename = None
self._lineno = 0 self._lineno = 0
self._filelineno = 0 self._filelineno = 0
self._file = None self._file = None
self._isstdin = 0 self._isstdin = 0
def __del__(self): def __del__(self):
self.close() self.close()
def close(self): def close(self):
self.nextfile() self.nextfile()
self._files = () self._files = ()
def __getitem__(self, i): def __getitem__(self, i):
if i != self._lineno: if i != self._lineno:
raise RuntimeError, "accessing lines out of order" raise RuntimeError, "accessing lines out of order"
line = self.readline() line = self.readline()
if not line: if not line:
raise IndexError, "end of input reached" raise IndexError, "end of input reached"
return line return line
def nextfile(self): def nextfile(self):
savestdout = self._savestdout savestdout = self._savestdout
self._savestdout = 0 self._savestdout = 0
if savestdout: if savestdout:
sys.stdout = savestdout sys.stdout = savestdout
output = self._output output = self._output
self._output = 0 self._output = 0
if output: if output:
output.close() output.close()
file = self._file file = self._file
self._file = 0 self._file = 0
if file and not self._isstdin: if file and not self._isstdin:
file.close() file.close()
backupfilename = self._backupfilename backupfilename = self._backupfilename
self._backupfilename = 0 self._backupfilename = 0
if backupfilename and not self._backup: if backupfilename and not self._backup:
try: os.unlink(backupfilename) try: os.unlink(backupfilename)
except: pass except: pass
self._isstdin = 0 self._isstdin = 0
def readline(self): def readline(self):
if not self._file: if not self._file:
if not self._files: if not self._files:
return "" return ""
self._filename = self._files[0] self._filename = self._files[0]
self._files = self._files[1:] self._files = self._files[1:]
self._filelineno = 0 self._filelineno = 0
self._file = None self._file = None
self._isstdin = 0 self._isstdin = 0
self._backupfilename = 0 self._backupfilename = 0
if self._filename == '-': if self._filename == '-':
self._filename = '<stdin>' self._filename = '<stdin>'
self._file = sys.stdin self._file = sys.stdin
self._isstdin = 1 self._isstdin = 1
else: else:
if self._inplace: if self._inplace:
self._backupfilename = ( self._backupfilename = (
self._filename + (self._backup or ".bak")) self._filename + (self._backup or ".bak"))
try: os.unlink(self._backupfilename) try: os.unlink(self._backupfilename)
except os.error: pass except os.error: pass
# The next three lines may raise IOError # The next three lines may raise IOError
os.rename(self._filename, self._backupfilename) os.rename(self._filename, self._backupfilename)
self._file = open(self._backupfilename, "r") self._file = open(self._backupfilename, "r")
self._output = open(self._filename, "w") self._output = open(self._filename, "w")
self._savestdout = sys.stdout self._savestdout = sys.stdout
sys.stdout = self._output sys.stdout = self._output
else: else:
# This may raise IOError # This may raise IOError
self._file = open(self._filename, "r") self._file = open(self._filename, "r")
line = self._file.readline() line = self._file.readline()
if line: if line:
self._lineno = self._lineno + 1 self._lineno = self._lineno + 1
self._filelineno = self._filelineno + 1 self._filelineno = self._filelineno + 1
return line return line
self.nextfile() self.nextfile()
# Recursive call # Recursive call
return self.readline() return self.readline()
def filename(self): def filename(self):
return self._filename return self._filename
def lineno(self): def lineno(self):
return self._lineno return self._lineno
def filelineno(self): def filelineno(self):
return self._filelineno return self._filelineno
def isfirstline(self): def isfirstline(self):
return self._filelineno == 1 return self._filelineno == 1
def isstdin(self): def isstdin(self):
return self._isstdin return self._isstdin
def _test(): def _test():
import getopt import getopt
...@@ -241,13 +241,13 @@ def _test(): ...@@ -241,13 +241,13 @@ def _test():
backup = 0 backup = 0
opts, args = getopt.getopt(sys.argv[1:], "ib:") opts, args = getopt.getopt(sys.argv[1:], "ib:")
for o, a in opts: for o, a in opts:
if o == '-i': inplace = 1 if o == '-i': inplace = 1
if o == '-b': backup = a if o == '-b': backup = a
for line in input(args, inplace=inplace, backup=backup): for line in input(args, inplace=inplace, backup=backup):
if line[-1:] == '\n': line = line[:-1] if line[-1:] == '\n': line = line[:-1]
if line[-1:] == '\r': line = line[:-1] if line[-1:] == '\r': line = line[:-1]
print "%d: %s[%d]%s %s" % (lineno(), filename(), filelineno(), print "%d: %s[%d]%s %s" % (lineno(), filename(), filelineno(),
isfirstline() and "*" or "", line) isfirstline() and "*" or "", line)
print "%d: %s[%d]" % (lineno(), filename(), filelineno()) print "%d: %s[%d]" % (lineno(), filename(), filelineno())
if __name__ == '__main__': if __name__ == '__main__':
......
...@@ -9,9 +9,9 @@ AS_IS = None ...@@ -9,9 +9,9 @@ AS_IS = None
class NullFormatter: class NullFormatter:
def __init__(self, writer=None): def __init__(self, writer=None):
if not writer: if not writer:
writer = NullWriter() writer = NullWriter()
self.writer = writer self.writer = writer
def end_paragraph(self, blankline): pass def end_paragraph(self, blankline): pass
def add_line_break(self): pass def add_line_break(self): pass
def add_hor_rule(self, *args, **kw): pass def add_hor_rule(self, *args, **kw): pass
...@@ -39,88 +39,88 @@ class AbstractFormatter: ...@@ -39,88 +39,88 @@ class AbstractFormatter:
# in all circumstances. # in all circumstances.
def __init__(self, writer): def __init__(self, writer):
self.writer = writer # Output device self.writer = writer # Output device
self.align = None # Current alignment self.align = None # Current alignment
self.align_stack = [] # Alignment stack self.align_stack = [] # Alignment stack
self.font_stack = [] # Font state self.font_stack = [] # Font state
self.margin_stack = [] # Margin state self.margin_stack = [] # Margin state
self.spacing = None # Vertical spacing state self.spacing = None # Vertical spacing state
self.style_stack = [] # Other state, e.g. color self.style_stack = [] # Other state, e.g. color
self.nospace = 1 # Should leading space be suppressed self.nospace = 1 # Should leading space be suppressed
self.softspace = 0 # Should a space be inserted self.softspace = 0 # Should a space be inserted
self.para_end = 1 # Just ended a paragraph self.para_end = 1 # Just ended a paragraph
self.parskip = 0 # Skipped space between paragraphs? self.parskip = 0 # Skipped space between paragraphs?
self.hard_break = 1 # Have a hard break self.hard_break = 1 # Have a hard break
self.have_label = 0 self.have_label = 0
def end_paragraph(self, blankline): def end_paragraph(self, blankline):
if not self.hard_break: if not self.hard_break:
self.writer.send_line_break() self.writer.send_line_break()
self.have_label = 0 self.have_label = 0
if self.parskip < blankline and not self.have_label: if self.parskip < blankline and not self.have_label:
self.writer.send_paragraph(blankline - self.parskip) self.writer.send_paragraph(blankline - self.parskip)
self.parskip = blankline self.parskip = blankline
self.have_label = 0 self.have_label = 0
self.hard_break = self.nospace = self.para_end = 1 self.hard_break = self.nospace = self.para_end = 1
self.softspace = 0 self.softspace = 0
def add_line_break(self): def add_line_break(self):
if not (self.hard_break or self.para_end): if not (self.hard_break or self.para_end):
self.writer.send_line_break() self.writer.send_line_break()
self.have_label = self.parskip = 0 self.have_label = self.parskip = 0
self.hard_break = self.nospace = 1 self.hard_break = self.nospace = 1
self.softspace = 0 self.softspace = 0
def add_hor_rule(self, *args, **kw): def add_hor_rule(self, *args, **kw):
if not self.hard_break: if not self.hard_break:
self.writer.send_line_break() self.writer.send_line_break()
apply(self.writer.send_hor_rule, args, kw) apply(self.writer.send_hor_rule, args, kw)
self.hard_break = self.nospace = 1 self.hard_break = self.nospace = 1
self.have_label = self.para_end = self.softspace = self.parskip = 0 self.have_label = self.para_end = self.softspace = self.parskip = 0
def add_label_data(self, format, counter, blankline = None): def add_label_data(self, format, counter, blankline = None):
if self.have_label or not self.hard_break: if self.have_label or not self.hard_break:
self.writer.send_line_break() self.writer.send_line_break()
if not self.para_end: if not self.para_end:
self.writer.send_paragraph((blankline and 1) or 0) self.writer.send_paragraph((blankline and 1) or 0)
if type(format) is StringType: if type(format) is StringType:
self.writer.send_label_data(self.format_counter(format, counter)) self.writer.send_label_data(self.format_counter(format, counter))
else: else:
self.writer.send_label_data(format) self.writer.send_label_data(format)
self.nospace = self.have_label = self.hard_break = self.para_end = 1 self.nospace = self.have_label = self.hard_break = self.para_end = 1
self.softspace = self.parskip = 0 self.softspace = self.parskip = 0
def format_counter(self, format, counter): def format_counter(self, format, counter):
label = '' label = ''
for c in format: for c in format:
try: try:
if c == '1': if c == '1':
label = label + ('%d' % counter) label = label + ('%d' % counter)
elif c in 'aA': elif c in 'aA':
if counter > 0: if counter > 0:
label = label + self.format_letter(c, counter) label = label + self.format_letter(c, counter)
elif c in 'iI': elif c in 'iI':
if counter > 0: if counter > 0:
label = label + self.format_roman(c, counter) label = label + self.format_roman(c, counter)
else: else:
label = label + c label = label + c
except: except:
label = label + c label = label + c
return label return label
def format_letter(self, case, counter): def format_letter(self, case, counter):
label = '' label = ''
while counter > 0: while counter > 0:
counter, x = divmod(counter-1, 26) counter, x = divmod(counter-1, 26)
s = chr(ord(case) + x) s = chr(ord(case) + x)
label = s + label label = s + label
return label return label
def format_roman(self, case, counter): def format_roman(self, case, counter):
ones = ['i', 'x', 'c', 'm'] ones = ['i', 'x', 'c', 'm']
fives = ['v', 'l', 'd'] fives = ['v', 'l', 'd']
label, index = '', 0 label, index = '', 0
# This will die of IndexError when counter is too big # This will die of IndexError when counter is too big
while counter > 0: while counter > 0:
counter, x = divmod(counter, 10) counter, x = divmod(counter, 10)
if x == 9: if x == 9:
...@@ -134,132 +134,132 @@ class AbstractFormatter: ...@@ -134,132 +134,132 @@ class AbstractFormatter:
else: else:
s = '' s = ''
s = s + ones[index]*x s = s + ones[index]*x
label = s + label label = s + label
index = index + 1 index = index + 1
if case == 'I': if case == 'I':
return string.upper(label) return string.upper(label)
return label return label
def add_flowing_data(self, data, def add_flowing_data(self, data,
# These are only here to load them into locals: # These are only here to load them into locals:
whitespace = string.whitespace, whitespace = string.whitespace,
join = string.join, split = string.split): join = string.join, split = string.split):
if not data: return if not data: return
# The following looks a bit convoluted but is a great improvement over # The following looks a bit convoluted but is a great improvement over
# data = regsub.gsub('[' + string.whitespace + ']+', ' ', data) # data = regsub.gsub('[' + string.whitespace + ']+', ' ', data)
prespace = data[:1] in whitespace prespace = data[:1] in whitespace
postspace = data[-1:] in whitespace postspace = data[-1:] in whitespace
data = join(split(data)) data = join(split(data))
if self.nospace and not data: if self.nospace and not data:
return return
elif prespace or self.softspace: elif prespace or self.softspace:
if not data: if not data:
if not self.nospace: if not self.nospace:
self.softspace = 1 self.softspace = 1
self.parskip = 0 self.parskip = 0
return return
if not self.nospace: if not self.nospace:
data = ' ' + data data = ' ' + data
self.hard_break = self.nospace = self.para_end = \ self.hard_break = self.nospace = self.para_end = \
self.parskip = self.have_label = 0 self.parskip = self.have_label = 0
self.softspace = postspace self.softspace = postspace
self.writer.send_flowing_data(data) self.writer.send_flowing_data(data)
def add_literal_data(self, data): def add_literal_data(self, data):
if not data: return if not data: return
if self.softspace: if self.softspace:
self.writer.send_flowing_data(" ") self.writer.send_flowing_data(" ")
self.hard_break = data[-1:] == '\n' self.hard_break = data[-1:] == '\n'
self.nospace = self.para_end = self.softspace = \ self.nospace = self.para_end = self.softspace = \
self.parskip = self.have_label = 0 self.parskip = self.have_label = 0
self.writer.send_literal_data(data) self.writer.send_literal_data(data)
def flush_softspace(self): def flush_softspace(self):
if self.softspace: if self.softspace:
self.hard_break = self.para_end = self.parskip = \ self.hard_break = self.para_end = self.parskip = \
self.have_label = self.softspace = 0 self.have_label = self.softspace = 0
self.nospace = 1 self.nospace = 1
self.writer.send_flowing_data(' ') self.writer.send_flowing_data(' ')
def push_alignment(self, align): def push_alignment(self, align):
if align and align != self.align: if align and align != self.align:
self.writer.new_alignment(align) self.writer.new_alignment(align)
self.align = align self.align = align
self.align_stack.append(align) self.align_stack.append(align)
else: else:
self.align_stack.append(self.align) self.align_stack.append(self.align)
def pop_alignment(self): def pop_alignment(self):
if self.align_stack: if self.align_stack:
del self.align_stack[-1] del self.align_stack[-1]
if self.align_stack: if self.align_stack:
self.align = align = self.align_stack[-1] self.align = align = self.align_stack[-1]
self.writer.new_alignment(align) self.writer.new_alignment(align)
else: else:
self.align = None self.align = None
self.writer.new_alignment(None) self.writer.new_alignment(None)
def push_font(self, (size, i, b, tt)): def push_font(self, (size, i, b, tt)):
if self.softspace: if self.softspace:
self.hard_break = self.para_end = self.softspace = 0 self.hard_break = self.para_end = self.softspace = 0
self.nospace = 1 self.nospace = 1
self.writer.send_flowing_data(' ') self.writer.send_flowing_data(' ')
if self.font_stack: if self.font_stack:
csize, ci, cb, ctt = self.font_stack[-1] csize, ci, cb, ctt = self.font_stack[-1]
if size is AS_IS: size = csize if size is AS_IS: size = csize
if i is AS_IS: i = ci if i is AS_IS: i = ci
if b is AS_IS: b = cb if b is AS_IS: b = cb
if tt is AS_IS: tt = ctt if tt is AS_IS: tt = ctt
font = (size, i, b, tt) font = (size, i, b, tt)
self.font_stack.append(font) self.font_stack.append(font)
self.writer.new_font(font) self.writer.new_font(font)
def pop_font(self): def pop_font(self):
if self.font_stack: if self.font_stack:
del self.font_stack[-1] del self.font_stack[-1]
if self.font_stack: if self.font_stack:
font = self.font_stack[-1] font = self.font_stack[-1]
else: else:
font = None font = None
self.writer.new_font(font) self.writer.new_font(font)
def push_margin(self, margin): def push_margin(self, margin):
self.margin_stack.append(margin) self.margin_stack.append(margin)
fstack = filter(None, self.margin_stack) fstack = filter(None, self.margin_stack)
if not margin and fstack: if not margin and fstack:
margin = fstack[-1] margin = fstack[-1]
self.writer.new_margin(margin, len(fstack)) self.writer.new_margin(margin, len(fstack))
def pop_margin(self): def pop_margin(self):
if self.margin_stack: if self.margin_stack:
del self.margin_stack[-1] del self.margin_stack[-1]
fstack = filter(None, self.margin_stack) fstack = filter(None, self.margin_stack)
if fstack: if fstack:
margin = fstack[-1] margin = fstack[-1]
else: else:
margin = None margin = None
self.writer.new_margin(margin, len(fstack)) self.writer.new_margin(margin, len(fstack))
def set_spacing(self, spacing): def set_spacing(self, spacing):
self.spacing = spacing self.spacing = spacing
self.writer.new_spacing(spacing) self.writer.new_spacing(spacing)
def push_style(self, *styles): def push_style(self, *styles):
if self.softspace: if self.softspace:
self.hard_break = self.para_end = self.softspace = 0 self.hard_break = self.para_end = self.softspace = 0
self.nospace = 1 self.nospace = 1
self.writer.send_flowing_data(' ') self.writer.send_flowing_data(' ')
for style in styles: for style in styles:
self.style_stack.append(style) self.style_stack.append(style)
self.writer.new_styles(tuple(self.style_stack)) self.writer.new_styles(tuple(self.style_stack))
def pop_style(self, n=1): def pop_style(self, n=1):
del self.style_stack[-n:] del self.style_stack[-n:]
self.writer.new_styles(tuple(self.style_stack)) self.writer.new_styles(tuple(self.style_stack))
def assert_line_data(self, flag=1): def assert_line_data(self, flag=1):
self.nospace = self.hard_break = not flag self.nospace = self.hard_break = not flag
self.para_end = self.parskip = self.have_label = 0 self.para_end = self.parskip = self.have_label = 0
class NullWriter: class NullWriter:
...@@ -282,119 +282,119 @@ class NullWriter: ...@@ -282,119 +282,119 @@ class NullWriter:
class AbstractWriter(NullWriter): class AbstractWriter(NullWriter):
def __init__(self): def __init__(self):
pass pass
def new_alignment(self, align): def new_alignment(self, align):
print "new_alignment(%s)" % `align` print "new_alignment(%s)" % `align`
def new_font(self, font): def new_font(self, font):
print "new_font(%s)" % `font` print "new_font(%s)" % `font`
def new_margin(self, margin, level): def new_margin(self, margin, level):
print "new_margin(%s, %d)" % (`margin`, level) print "new_margin(%s, %d)" % (`margin`, level)
def new_spacing(self, spacing): def new_spacing(self, spacing):
print "new_spacing(%s)" % `spacing` print "new_spacing(%s)" % `spacing`
def new_styles(self, styles): def new_styles(self, styles):
print "new_styles(%s)" % `styles` print "new_styles(%s)" % `styles`
def send_paragraph(self, blankline): def send_paragraph(self, blankline):
print "send_paragraph(%s)" % `blankline` print "send_paragraph(%s)" % `blankline`
def send_line_break(self): def send_line_break(self):
print "send_line_break()" print "send_line_break()"
def send_hor_rule(self, *args, **kw): def send_hor_rule(self, *args, **kw):
print "send_hor_rule()" print "send_hor_rule()"
def send_label_data(self, data): def send_label_data(self, data):
print "send_label_data(%s)" % `data` print "send_label_data(%s)" % `data`
def send_flowing_data(self, data): def send_flowing_data(self, data):
print "send_flowing_data(%s)" % `data` print "send_flowing_data(%s)" % `data`
def send_literal_data(self, data): def send_literal_data(self, data):
print "send_literal_data(%s)" % `data` print "send_literal_data(%s)" % `data`
class DumbWriter(NullWriter): class DumbWriter(NullWriter):
def __init__(self, file=None, maxcol=72): def __init__(self, file=None, maxcol=72):
self.file = file or sys.stdout self.file = file or sys.stdout
self.maxcol = maxcol self.maxcol = maxcol
NullWriter.__init__(self) NullWriter.__init__(self)
self.reset() self.reset()
def reset(self): def reset(self):
self.col = 0 self.col = 0
self.atbreak = 0 self.atbreak = 0
def send_paragraph(self, blankline): def send_paragraph(self, blankline):
self.file.write('\n' + '\n'*blankline) self.file.write('\n' + '\n'*blankline)
self.col = 0 self.col = 0
self.atbreak = 0 self.atbreak = 0
def send_line_break(self): def send_line_break(self):
self.file.write('\n') self.file.write('\n')
self.col = 0 self.col = 0
self.atbreak = 0 self.atbreak = 0
def send_hor_rule(self, *args, **kw): def send_hor_rule(self, *args, **kw):
self.file.write('\n') self.file.write('\n')
self.file.write('-'*self.maxcol) self.file.write('-'*self.maxcol)
self.file.write('\n') self.file.write('\n')
self.col = 0 self.col = 0
self.atbreak = 0 self.atbreak = 0
def send_literal_data(self, data): def send_literal_data(self, data):
self.file.write(data) self.file.write(data)
i = string.rfind(data, '\n') i = string.rfind(data, '\n')
if i >= 0: if i >= 0:
self.col = 0 self.col = 0
data = data[i+1:] data = data[i+1:]
data = string.expandtabs(data) data = string.expandtabs(data)
self.col = self.col + len(data) self.col = self.col + len(data)
self.atbreak = 0 self.atbreak = 0
def send_flowing_data(self, data): def send_flowing_data(self, data):
if not data: return if not data: return
atbreak = self.atbreak or data[0] in string.whitespace atbreak = self.atbreak or data[0] in string.whitespace
col = self.col col = self.col
maxcol = self.maxcol maxcol = self.maxcol
write = self.file.write write = self.file.write
for word in string.split(data): for word in string.split(data):
if atbreak: if atbreak:
if col + len(word) >= maxcol: if col + len(word) >= maxcol:
write('\n') write('\n')
col = 0 col = 0
else: else:
write(' ') write(' ')
col = col + 1 col = col + 1
write(word) write(word)
col = col + len(word) col = col + len(word)
atbreak = 1 atbreak = 1
self.col = col self.col = col
self.atbreak = data[-1] in string.whitespace self.atbreak = data[-1] in string.whitespace
def test(file = None): def test(file = None):
w = DumbWriter() w = DumbWriter()
f = AbstractFormatter(w) f = AbstractFormatter(w)
if file: if file:
fp = open(file) fp = open(file)
elif sys.argv[1:]: elif sys.argv[1:]:
fp = open(sys.argv[1]) fp = open(sys.argv[1])
else: else:
fp = sys.stdin fp = sys.stdin
while 1: while 1:
line = fp.readline() line = fp.readline()
if not line: if not line:
break break
if line == '\n': if line == '\n':
f.end_paragraph(1) f.end_paragraph(1)
else: else:
f.add_flowing_data(line) f.add_flowing_data(line)
f.end_paragraph(0) f.end_paragraph(0)
......
...@@ -38,10 +38,10 @@ A_PLUS_SOUND = '<' ...@@ -38,10 +38,10 @@ A_PLUS_SOUND = '<'
# Function mapping all file types to strings; unknown types become TYPE='x' # Function mapping all file types to strings; unknown types become TYPE='x'
_names = dir() _names = dir()
_type_to_name_map = None _type_to_name_map = {}
def type_to_name(gtype): def type_to_name(gtype):
global _type_to_name_map global _type_to_name_map
if not _type_to_name_map: if _type_to_name_map=={}:
for name in _names: for name in _names:
if name[:2] == 'A_': if name[:2] == 'A_':
_type_to_name_map[eval(name)] = name[2:] _type_to_name_map[eval(name)] = name[2:]
...@@ -75,6 +75,22 @@ def send_selector(selector, host, port = 0): ...@@ -75,6 +75,22 @@ def send_selector(selector, host, port = 0):
def send_query(selector, query, host, port = 0): def send_query(selector, query, host, port = 0):
return send_selector(selector + '\t' + query, host, port) return send_selector(selector + '\t' + query, host, port)
# Takes a path as returned by urlparse and returns the appropriate selector
def path_to_selector(path):
if path=="/":
return "/"
else:
return path[2:] # Cuts initial slash and data type identifier
# Takes a path as returned by urlparse and maps it to a string
# See section 3.4 of RFC 1738 for details
def path_to_datatype_name(path):
if path=="/":
# No way to tell, although "INDEX" is likely
return "TYPE='unknown'"
else:
return type_to_name(path[1])
# The following functions interpret the data returned by the gopher # The following functions interpret the data returned by the gopher
# server according to the expected type, e.g. textfile or directory # server according to the expected type, e.g. textfile or directory
...@@ -103,7 +119,8 @@ def get_directory(f): ...@@ -103,7 +119,8 @@ def get_directory(f):
continue continue
if len(parts) > 4: if len(parts) > 4:
if parts[4:] != ['+']: if parts[4:] != ['+']:
print '(Extra info from server:', parts[4:], ')' print '(Extra info from server:',
print parts[4:], ')'
else: else:
parts.append('') parts.append('')
parts.insert(0, gtype) parts.insert(0, gtype)
......
...@@ -12,71 +12,71 @@ def url2pathname(pathname): ...@@ -12,71 +12,71 @@ def url2pathname(pathname):
# #
tp = urllib.splittype(pathname)[0] tp = urllib.splittype(pathname)[0]
if tp and tp <> 'file': if tp and tp <> 'file':
raise RuntimeError, 'Cannot convert non-local URL to pathname' raise RuntimeError, 'Cannot convert non-local URL to pathname'
components = string.split(pathname, '/') components = string.split(pathname, '/')
# Remove . and embedded .. # Remove . and embedded ..
i = 0 i = 0
while i < len(components): while i < len(components):
if components[i] == '.': if components[i] == '.':
del components[i] del components[i]
elif components[i] == '..' and i > 0 and \ elif components[i] == '..' and i > 0 and \
components[i-1] not in ('', '..'): components[i-1] not in ('', '..'):
del components[i-1:i+1] del components[i-1:i+1]
i = i-1 i = i-1
elif components[i] == '' and i > 0 and components[i-1] <> '': elif components[i] == '' and i > 0 and components[i-1] <> '':
del components[i] del components[i]
else: else:
i = i+1 i = i+1
if not components[0]: if not components[0]:
# Absolute unix path, don't start with colon # Absolute unix path, don't start with colon
return string.join(components[1:], ':') return string.join(components[1:], ':')
else: else:
# relative unix path, start with colon. First replace # relative unix path, start with colon. First replace
# leading .. by empty strings (giving ::file) # leading .. by empty strings (giving ::file)
i = 0 i = 0
while i < len(components) and components[i] == '..': while i < len(components) and components[i] == '..':
components[i] = '' components[i] = ''
i = i + 1 i = i + 1
return ':' + string.join(components, ':') return ':' + string.join(components, ':')
def pathname2url(pathname): def pathname2url(pathname):
"convert mac pathname to /-delimited pathname" "convert mac pathname to /-delimited pathname"
if '/' in pathname: if '/' in pathname:
raise RuntimeError, "Cannot convert pathname containing slashes" raise RuntimeError, "Cannot convert pathname containing slashes"
components = string.split(pathname, ':') components = string.split(pathname, ':')
# Remove empty first and/or last component # Remove empty first and/or last component
if components[0] == '': if components[0] == '':
del components[0] del components[0]
if components[-1] == '': if components[-1] == '':
del components[-1] del components[-1]
# Replace empty string ('::') by .. (will result in '/../' later) # Replace empty string ('::') by .. (will result in '/../' later)
for i in range(len(components)): for i in range(len(components)):
if components[i] == '': if components[i] == '':
components[i] = '..' components[i] = '..'
# Truncate names longer than 31 bytes # Truncate names longer than 31 bytes
components = map(lambda x: x[:31], components) components = map(lambda x: x[:31], components)
if os.path.isabs(pathname): if os.path.isabs(pathname):
return '/' + string.join(components, '/') return '/' + string.join(components, '/')
else: else:
return string.join(components, '/') return string.join(components, '/')
def test(): def test():
for url in ["index.html", for url in ["index.html",
"bar/index.html", "bar/index.html",
"/foo/bar/index.html", "/foo/bar/index.html",
"/foo/bar/", "/foo/bar/",
"/"]: "/"]:
print `url`, '->', `url2pathname(url)` print `url`, '->', `url2pathname(url)`
for path in ["drive:", for path in ["drive:",
"drive:dir:", "drive:dir:",
"drive:dir:file", "drive:dir:file",
"drive:file", "drive:file",
"file", "file",
":file", ":file",
":dir:", ":dir:",
":dir:file"]: ":dir:file"]:
print `path`, '->', `pathname2url(path)` print `path`, '->', `pathname2url(path)`
if __name__ == '__main__': if __name__ == '__main__':
test() test()
...@@ -48,49 +48,49 @@ def guess_type(url): ...@@ -48,49 +48,49 @@ def guess_type(url):
""" """
if not inited: if not inited:
init() init()
base, ext = posixpath.splitext(url) base, ext = posixpath.splitext(url)
while suffix_map.has_key(ext): while suffix_map.has_key(ext):
base, ext = posixpath.splitext(base + suffix_map[ext]) base, ext = posixpath.splitext(base + suffix_map[ext])
if encodings_map.has_key(ext): if encodings_map.has_key(ext):
encoding = encodings_map[ext] encoding = encodings_map[ext]
base, ext = posixpath.splitext(base) base, ext = posixpath.splitext(base)
else: else:
encoding = None encoding = None
if types_map.has_key(ext): if types_map.has_key(ext):
return types_map[ext], encoding return types_map[ext], encoding
elif types_map.has_key(string.lower(ext)): elif types_map.has_key(string.lower(ext)):
return types_map[string.lower(ext)], encoding return types_map[string.lower(ext)], encoding
else: else:
return None, encoding return None, encoding
def init(files=None): def init(files=None):
global inited global inited
for file in files or knownfiles: for file in files or knownfiles:
s = read_mime_types(file) s = read_mime_types(file)
if s: if s:
for key, value in s.items(): for key, value in s.items():
types_map[key] = value types_map[key] = value
inited = 1 inited = 1
def read_mime_types(file): def read_mime_types(file):
try: try:
f = open(file) f = open(file)
except IOError: except IOError:
return None return None
map = {} map = {}
while 1: while 1:
line = f.readline() line = f.readline()
if not line: break if not line: break
words = string.split(line) words = string.split(line)
for i in range(len(words)): for i in range(len(words)):
if words[i][0] == '#': if words[i][0] == '#':
del words[i:] del words[i:]
break break
if not words: continue if not words: continue
type, suffixes = words[0], words[1:] type, suffixes = words[0], words[1:]
for suff in suffixes: for suff in suffixes:
map['.'+suff] = type map['.'+suff] = type
f.close() f.close()
return map return map
......
...@@ -47,7 +47,7 @@ class MimeWriter: ...@@ -47,7 +47,7 @@ class MimeWriter:
w.startmultipartbody(subtype) w.startmultipartbody(subtype)
for each part: for each part:
subwriter = w.nextpart() subwriter = w.nextpart()
...use the subwriter's methods to create the subpart... ...use the subwriter's methods to create the subpart...
w.lastpart() w.lastpart()
The subwriter is another MimeWriter instance, and should be The subwriter is another MimeWriter instance, and should be
...@@ -82,46 +82,46 @@ class MimeWriter: ...@@ -82,46 +82,46 @@ class MimeWriter:
""" """
def __init__(self, fp): def __init__(self, fp):
self._fp = fp self._fp = fp
self._headers = [] self._headers = []
def addheader(self, key, value, prefix=0): def addheader(self, key, value, prefix=0):
lines = string.splitfields(value, "\n") lines = string.splitfields(value, "\n")
while lines and not lines[-1]: del lines[-1] while lines and not lines[-1]: del lines[-1]
while lines and not lines[0]: del lines[0] while lines and not lines[0]: del lines[0]
for i in range(1, len(lines)): for i in range(1, len(lines)):
lines[i] = " " + string.strip(lines[i]) lines[i] = " " + string.strip(lines[i])
value = string.joinfields(lines, "\n") + "\n" value = string.joinfields(lines, "\n") + "\n"
line = key + ": " + value line = key + ": " + value
if prefix: if prefix:
self._headers.insert(0, line) self._headers.insert(0, line)
else: else:
self._headers.append(line) self._headers.append(line)
def flushheaders(self): def flushheaders(self):
self._fp.writelines(self._headers) self._fp.writelines(self._headers)
self._headers = [] self._headers = []
def startbody(self, ctype, plist=[], prefix=1): def startbody(self, ctype, plist=[], prefix=1):
for name, value in plist: for name, value in plist:
ctype = ctype + ';\n %s=\"%s\"' % (name, value) ctype = ctype + ';\n %s=\"%s\"' % (name, value)
self.addheader("Content-Type", ctype, prefix=prefix) self.addheader("Content-Type", ctype, prefix=prefix)
self.flushheaders() self.flushheaders()
self._fp.write("\n") self._fp.write("\n")
return self._fp return self._fp
def startmultipartbody(self, subtype, boundary=None, plist=[], prefix=1): def startmultipartbody(self, subtype, boundary=None, plist=[], prefix=1):
self._boundary = boundary or mimetools.choose_boundary() self._boundary = boundary or mimetools.choose_boundary()
return self.startbody("multipart/" + subtype, return self.startbody("multipart/" + subtype,
[("boundary", self._boundary)] + plist, [("boundary", self._boundary)] + plist,
prefix=prefix) prefix=prefix)
def nextpart(self): def nextpart(self):
self._fp.write("\n--" + self._boundary + "\n") self._fp.write("\n--" + self._boundary + "\n")
return self.__class__(self._fp) return self.__class__(self._fp)
def lastpart(self): def lastpart(self):
self._fp.write("\n--" + self._boundary + "--\n") self._fp.write("\n--" + self._boundary + "--\n")
if __name__ == '__main__': if __name__ == '__main__':
......
...@@ -44,8 +44,17 @@ class MultiFile: ...@@ -44,8 +44,17 @@ class MultiFile:
return self.lastpos return self.lastpos
return self.fp.tell() - self.start return self.fp.tell() - self.start
# #
def seek(self, pos): def seek(self, pos, whence=0):
if not 0 <= pos <= self.tell() or \ here = self.tell()
if whence:
if whence == 1:
pos = pos + here
elif whence == 2:
if self.level > 0:
pos = pos + self.lastpos
else:
raise Error, "can't use whence=2 yet"
if not 0 <= pos <= here or \
self.level > 0 and pos > self.lastpos: self.level > 0 and pos > self.lastpos:
raise Error, 'bad MultiFile.seek() call' raise Error, 'bad MultiFile.seek() call'
self.fp.seek(pos + self.start) self.fp.seek(pos + self.start)
......
...@@ -6,56 +6,56 @@ ...@@ -6,56 +6,56 @@
# Extended file operations # Extended file operations
# #
# f = posixfile.open(filename, [mode, [bufsize]]) # f = posixfile.open(filename, [mode, [bufsize]])
# will create a new posixfile object # will create a new posixfile object
# #
# f = posixfile.fileopen(fileobject) # f = posixfile.fileopen(fileobject)
# will create a posixfile object from a builtin file object # will create a posixfile object from a builtin file object
# #
# f.file() # f.file()
# will return the original builtin file object # will return the original builtin file object
# #
# f.dup() # f.dup()
# will return a new file object based on a new filedescriptor # will return a new file object based on a new filedescriptor
# #
# f.dup2(fd) # f.dup2(fd)
# will return a new file object based on the given filedescriptor # will return a new file object based on the given filedescriptor
# #
# f.flags(mode) # f.flags(mode)
# will turn on the associated flag (merge) # will turn on the associated flag (merge)
# mode can contain the following characters: # mode can contain the following characters:
# #
# (character representing a flag) # (character representing a flag)
# a append only flag # a append only flag
# c close on exec flag # c close on exec flag
# n no delay flag # n no delay flag
# s synchronization flag # s synchronization flag
# (modifiers) # (modifiers)
# ! turn flags 'off' instead of default 'on' # ! turn flags 'off' instead of default 'on'
# = copy flags 'as is' instead of default 'merge' # = copy flags 'as is' instead of default 'merge'
# ? return a string in which the characters represent the flags # ? return a string in which the characters represent the flags
# that are set # that are set
# #
# note: - the '!' and '=' modifiers are mutually exclusive. # note: - the '!' and '=' modifiers are mutually exclusive.
# - the '?' modifier will return the status of the flags after they # - the '?' modifier will return the status of the flags after they
# have been changed by other characters in the mode string # have been changed by other characters in the mode string
# #
# f.lock(mode [, len [, start [, whence]]]) # f.lock(mode [, len [, start [, whence]]])
# will (un)lock a region # will (un)lock a region
# mode can contain the following characters: # mode can contain the following characters:
# #
# (character representing type of lock) # (character representing type of lock)
# u unlock # u unlock
# r read lock # r read lock
# w write lock # w write lock
# (modifiers) # (modifiers)
# | wait until the lock can be granted # | wait until the lock can be granted
# ? return the first lock conflicting with the requested lock # ? return the first lock conflicting with the requested lock
# or 'None' if there is no conflict. The lock returned is in the # or 'None' if there is no conflict. The lock returned is in the
# format (mode, len, start, whence, pid) where mode is a # format (mode, len, start, whence, pid) where mode is a
# character representing the type of lock ('r' or 'w') # character representing the type of lock ('r' or 'w')
# #
# note: - the '?' modifier prevents a region from being locked; it is # note: - the '?' modifier prevents a region from being locked; it is
# query only # query only
# #
class _posixfile_: class _posixfile_:
...@@ -65,149 +65,149 @@ class _posixfile_: ...@@ -65,149 +65,149 @@ class _posixfile_:
# Internal routines # Internal routines
# #
def __repr__(self): def __repr__(self):
file = self._file_ file = self._file_
return "<%s posixfile '%s', mode '%s' at %s>" % \ return "<%s posixfile '%s', mode '%s' at %s>" % \
(self.states[file.closed], file.name, file.mode, \ (self.states[file.closed], file.name, file.mode, \
hex(id(self))[2:]) hex(id(self))[2:])
def __del__(self): def __del__(self):
self._file_.close() self._file_.close()
# #
# Initialization routines # Initialization routines
# #
def open(self, name, mode='r', bufsize=-1): def open(self, name, mode='r', bufsize=-1):
import __builtin__ import __builtin__
return self.fileopen(__builtin__.open(name, mode, bufsize)) return self.fileopen(__builtin__.open(name, mode, bufsize))
def fileopen(self, file): def fileopen(self, file):
if `type(file)` != "<type 'file'>": if `type(file)` != "<type 'file'>":
raise TypeError, 'posixfile.fileopen() arg must be file object' raise TypeError, 'posixfile.fileopen() arg must be file object'
self._file_ = file self._file_ = file
# Copy basic file methods # Copy basic file methods
for method in file.__methods__: for method in file.__methods__:
setattr(self, method, getattr(file, method)) setattr(self, method, getattr(file, method))
return self return self
# #
# New methods # New methods
# #
def file(self): def file(self):
return self._file_ return self._file_
def dup(self): def dup(self):
import posix import posix
try: ignore = posix.fdopen try: ignore = posix.fdopen
except: raise AttributeError, 'dup() method unavailable' except: raise AttributeError, 'dup() method unavailable'
return posix.fdopen(posix.dup(self._file_.fileno()), self._file_.mode) return posix.fdopen(posix.dup(self._file_.fileno()), self._file_.mode)
def dup2(self, fd): def dup2(self, fd):
import posix import posix
try: ignore = posix.fdopen try: ignore = posix.fdopen
except: raise AttributeError, 'dup() method unavailable' except: raise AttributeError, 'dup() method unavailable'
posix.dup2(self._file_.fileno(), fd) posix.dup2(self._file_.fileno(), fd)
return posix.fdopen(fd, self._file_.mode) return posix.fdopen(fd, self._file_.mode)
def flags(self, *which): def flags(self, *which):
import fcntl, FCNTL import fcntl, FCNTL
if which: if which:
if len(which) > 1: if len(which) > 1:
raise TypeError, 'Too many arguments' raise TypeError, 'Too many arguments'
which = which[0] which = which[0]
else: which = '?' else: which = '?'
l_flags = 0 l_flags = 0
if 'n' in which: l_flags = l_flags | FCNTL.O_NDELAY if 'n' in which: l_flags = l_flags | FCNTL.O_NDELAY
if 'a' in which: l_flags = l_flags | FCNTL.O_APPEND if 'a' in which: l_flags = l_flags | FCNTL.O_APPEND
if 's' in which: l_flags = l_flags | FCNTL.O_SYNC if 's' in which: l_flags = l_flags | FCNTL.O_SYNC
file = self._file_ file = self._file_
if '=' not in which: if '=' not in which:
cur_fl = fcntl.fcntl(file.fileno(), FCNTL.F_GETFL, 0) cur_fl = fcntl.fcntl(file.fileno(), FCNTL.F_GETFL, 0)
if '!' in which: l_flags = cur_fl & ~ l_flags if '!' in which: l_flags = cur_fl & ~ l_flags
else: l_flags = cur_fl | l_flags else: l_flags = cur_fl | l_flags
l_flags = fcntl.fcntl(file.fileno(), FCNTL.F_SETFL, l_flags) l_flags = fcntl.fcntl(file.fileno(), FCNTL.F_SETFL, l_flags)
if 'c' in which: if 'c' in which:
arg = ('!' not in which) # 0 is don't, 1 is do close on exec arg = ('!' not in which) # 0 is don't, 1 is do close on exec
l_flags = fcntl.fcntl(file.fileno(), FCNTL.F_SETFD, arg) l_flags = fcntl.fcntl(file.fileno(), FCNTL.F_SETFD, arg)
if '?' in which: if '?' in which:
which = '' # Return current flags which = '' # Return current flags
l_flags = fcntl.fcntl(file.fileno(), FCNTL.F_GETFL, 0) l_flags = fcntl.fcntl(file.fileno(), FCNTL.F_GETFL, 0)
if FCNTL.O_APPEND & l_flags: which = which + 'a' if FCNTL.O_APPEND & l_flags: which = which + 'a'
if fcntl.fcntl(file.fileno(), FCNTL.F_GETFD, 0) & 1: if fcntl.fcntl(file.fileno(), FCNTL.F_GETFD, 0) & 1:
which = which + 'c' which = which + 'c'
if FCNTL.O_NDELAY & l_flags: which = which + 'n' if FCNTL.O_NDELAY & l_flags: which = which + 'n'
if FCNTL.O_SYNC & l_flags: which = which + 's' if FCNTL.O_SYNC & l_flags: which = which + 's'
return which return which
def lock(self, how, *args): def lock(self, how, *args):
import struct, fcntl, FCNTL import struct, fcntl, FCNTL
if 'w' in how: l_type = FCNTL.F_WRLCK if 'w' in how: l_type = FCNTL.F_WRLCK
elif 'r' in how: l_type = FCNTL.F_RDLCK elif 'r' in how: l_type = FCNTL.F_RDLCK
elif 'u' in how: l_type = FCNTL.F_UNLCK elif 'u' in how: l_type = FCNTL.F_UNLCK
else: raise TypeError, 'no type of lock specified' else: raise TypeError, 'no type of lock specified'
if '|' in how: cmd = FCNTL.F_SETLKW if '|' in how: cmd = FCNTL.F_SETLKW
elif '?' in how: cmd = FCNTL.F_GETLK elif '?' in how: cmd = FCNTL.F_GETLK
else: cmd = FCNTL.F_SETLK else: cmd = FCNTL.F_SETLK
l_whence = 0 l_whence = 0
l_start = 0 l_start = 0
l_len = 0 l_len = 0
if len(args) == 1: if len(args) == 1:
l_len = args[0] l_len = args[0]
elif len(args) == 2: elif len(args) == 2:
l_len, l_start = args l_len, l_start = args
elif len(args) == 3: elif len(args) == 3:
l_len, l_start, l_whence = args l_len, l_start, l_whence = args
elif len(args) > 3: elif len(args) > 3:
raise TypeError, 'too many arguments' raise TypeError, 'too many arguments'
# Hack by davem@magnet.com to get locking to go on freebsd; # Hack by davem@magnet.com to get locking to go on freebsd;
# additions for AIX by Vladimir.Marangozov@imag.fr # additions for AIX by Vladimir.Marangozov@imag.fr
import sys, os import sys, os
if sys.platform in ('netbsd1', 'freebsd2', 'freebsd3'): if sys.platform in ('netbsd1', 'freebsd2', 'freebsd3'):
flock = struct.pack('lxxxxlxxxxlhh', \ flock = struct.pack('lxxxxlxxxxlhh', \
l_start, l_len, os.getpid(), l_type, l_whence) l_start, l_len, os.getpid(), l_type, l_whence)
elif sys.platform in ['aix3', 'aix4']: elif sys.platform in ['aix3', 'aix4']:
flock = struct.pack('hhlllii', \ flock = struct.pack('hhlllii', \
l_type, l_whence, l_start, l_len, 0, 0, 0) l_type, l_whence, l_start, l_len, 0, 0, 0)
else: else:
flock = struct.pack('hhllhh', \ flock = struct.pack('hhllhh', \
l_type, l_whence, l_start, l_len, 0, 0) l_type, l_whence, l_start, l_len, 0, 0)
flock = fcntl.fcntl(self._file_.fileno(), cmd, flock) flock = fcntl.fcntl(self._file_.fileno(), cmd, flock)
if '?' in how: if '?' in how:
if sys.platform in ('netbsd1', 'freebsd2', 'freebsd3'): if sys.platform in ('netbsd1', 'freebsd2', 'freebsd3'):
l_start, l_len, l_pid, l_type, l_whence = \ l_start, l_len, l_pid, l_type, l_whence = \
struct.unpack('lxxxxlxxxxlhh', flock) struct.unpack('lxxxxlxxxxlhh', flock)
elif sys.platform in ['aix3', 'aix4']: elif sys.platform in ['aix3', 'aix4']:
l_type, l_whence, l_start, l_len, l_sysid, l_pid, l_vfs = \ l_type, l_whence, l_start, l_len, l_sysid, l_pid, l_vfs = \
struct.unpack('hhlllii', flock) struct.unpack('hhlllii', flock)
elif sys.platform == "linux2": elif sys.platform == "linux2":
l_type, l_whence, l_start, l_len, l_pid, l_sysid = \ l_type, l_whence, l_start, l_len, l_pid, l_sysid = \
struct.unpack('hhllhh', flock) struct.unpack('hhllhh', flock)
else: else:
l_type, l_whence, l_start, l_len, l_sysid, l_pid = \ l_type, l_whence, l_start, l_len, l_sysid, l_pid = \
struct.unpack('hhllhh', flock) struct.unpack('hhllhh', flock)
if l_type != FCNTL.F_UNLCK: if l_type != FCNTL.F_UNLCK:
if l_type == FCNTL.F_RDLCK: if l_type == FCNTL.F_RDLCK:
return 'r', l_len, l_start, l_whence, l_pid return 'r', l_len, l_start, l_whence, l_pid
else: else:
return 'w', l_len, l_start, l_whence, l_pid return 'w', l_len, l_start, l_whence, l_pid
# #
# Public routine to obtain a posixfile object # Public routine to obtain a posixfile object
......
# Routine to "compile" a .py file to a .pyc file. """Routine to "compile" a .py file to a .pyc (or .pyo) file.
# This has intimate knowledge of how Python/import.c does it.
# By Sjoerd Mullender (I forced him to write it :-). This module has intimate knowledge of the format of .pyc files.
"""
import imp import imp
MAGIC = imp.get_magic() MAGIC = imp.get_magic()
def wr_long(f, x): def wr_long(f, x):
f.write(chr( x & 0xff)) "Internal; write a 32-bit int to a file in little-endian order."
f.write(chr((x >> 8) & 0xff)) f.write(chr( x & 0xff))
f.write(chr((x >> 16) & 0xff)) f.write(chr((x >> 8) & 0xff))
f.write(chr((x >> 24) & 0xff)) f.write(chr((x >> 16) & 0xff))
f.write(chr((x >> 24) & 0xff))
def compile(file, cfile = None):
import os, marshal, __builtin__ def compile(file, cfile=None, dfile=None):
f = open(file) """Byte-compile one Python source file to Python bytecode.
try:
timestamp = os.fstat(file.fileno()) Arguments:
except AttributeError:
timestamp = long(os.stat(file)[8]) file: source filename
codestring = f.read() cfile: target filename; defaults to source with 'c' or 'o' appended
f.close() ('c' normally, 'o' in optimizing mode, giving .pyc or .pyo)
codeobject = __builtin__.compile(codestring, file, 'exec') dfile: purported filename; defaults to source (this is the filename
if not cfile: that will show up in error messages)
cfile = file + (__debug__ and 'c' or 'o')
fc = open(cfile, 'wb') Note that it isn't necessary to byte-compile Python modules for
fc.write('\0\0\0\0') execution efficiency -- Python itself byte-compiles a module when
wr_long(fc, timestamp) it is loaded, and if it can, writes out the bytecode to the
marshal.dump(codeobject, fc) corresponding .pyc (or .pyo) file.
fc.flush()
fc.seek(0, 0) However, if a Python installation is shared between users, it is a
fc.write(MAGIC) good idea to byte-compile all modules upon installation, since
fc.close() other users may not be able to write in the source directories,
if os.name == 'mac': and thus they won't be able to write the .pyc/.pyo file, and then
import macfs they would be byte-compiling every module each time it is loaded.
macfs.FSSpec(cfile).SetCreatorType('Pyth', 'PYC ') This can slow down program start-up considerably.
macfs.FSSpec(file).SetCreatorType('Pyth', 'TEXT')
See compileall.py for a script/module that uses this module to
byte-compile all installed files (or all files in selected
directories).
"""
import os, marshal, __builtin__
f = open(file)
try:
timestamp = os.fstat(file.fileno())
except AttributeError:
timestamp = long(os.stat(file)[8])
codestring = f.read()
f.close()
if codestring and codestring[-1] != '\n':
codestring = codestring + '\n'
codeobject = __builtin__.compile(codestring, dfile or file, 'exec')
if not cfile:
cfile = file + (__debug__ and 'c' or 'o')
fc = open(cfile, 'wb')
fc.write('\0\0\0\0')
wr_long(fc, timestamp)
marshal.dump(codeobject, fc)
fc.flush()
fc.seek(0, 0)
fc.write(MAGIC)
fc.close()
if os.name == 'mac':
import macfs
macfs.FSSpec(cfile).SetCreatorType('Pyth', 'PYC ')
macfs.FSSpec(file).SetCreatorType('Pyth', 'TEXT')
...@@ -4,102 +4,102 @@ ...@@ -4,102 +4,102 @@
# exceptions, but also when -X option is used. # exceptions, but also when -X option is used.
try: try:
class Empty(Exception): class Empty(Exception):
pass pass
except TypeError: except TypeError:
# string based exceptions # string based exceptions
Empty = 'Queue.Empty' # Exception raised by get_nowait() Empty = 'Queue.Empty' # Exception raised by get_nowait()
class Queue: class Queue:
def __init__(self, maxsize): def __init__(self, maxsize):
"""Initialize a queue object with a given maximum size. """Initialize a queue object with a given maximum size.
If maxsize is <= 0, the queue size is infinite. If maxsize is <= 0, the queue size is infinite.
""" """
import thread import thread
self._init(maxsize) self._init(maxsize)
self.mutex = thread.allocate_lock() self.mutex = thread.allocate_lock()
self.esema = thread.allocate_lock() self.esema = thread.allocate_lock()
self.esema.acquire_lock() self.esema.acquire_lock()
self.fsema = thread.allocate_lock() self.fsema = thread.allocate_lock()
def qsize(self): def qsize(self):
"""Returns the approximate size of the queue (not reliable!).""" """Returns the approximate size of the queue (not reliable!)."""
self.mutex.acquire_lock() self.mutex.acquire_lock()
n = self._qsize() n = self._qsize()
self.mutex.release_lock() self.mutex.release_lock()
return n return n
def empty(self): def empty(self):
"""Returns 1 if the queue is empty, 0 otherwise (not reliable!).""" """Returns 1 if the queue is empty, 0 otherwise (not reliable!)."""
self.mutex.acquire_lock() self.mutex.acquire_lock()
n = self._empty() n = self._empty()
self.mutex.release_lock() self.mutex.release_lock()
return n return n
def full(self): def full(self):
"""Returns 1 if the queue is full, 0 otherwise (not reliable!).""" """Returns 1 if the queue is full, 0 otherwise (not reliable!)."""
self.mutex.acquire_lock() self.mutex.acquire_lock()
n = self._full() n = self._full()
self.mutex.release_lock() self.mutex.release_lock()
return n return n
def put(self, item): def put(self, item):
"""Put an item into the queue.""" """Put an item into the queue."""
self.fsema.acquire_lock() self.fsema.acquire_lock()
self.mutex.acquire_lock() self.mutex.acquire_lock()
was_empty = self._empty() was_empty = self._empty()
self._put(item) self._put(item)
if was_empty: if was_empty:
self.esema.release_lock() self.esema.release_lock()
if not self._full(): if not self._full():
self.fsema.release_lock() self.fsema.release_lock()
self.mutex.release_lock() self.mutex.release_lock()
def get(self): def get(self):
"""Gets and returns an item from the queue. """Gets and returns an item from the queue.
This method blocks if necessary until an item is available. This method blocks if necessary until an item is available.
""" """
self.esema.acquire_lock() self.esema.acquire_lock()
self.mutex.acquire_lock() self.mutex.acquire_lock()
was_full = self._full() was_full = self._full()
item = self._get() item = self._get()
if was_full: if was_full:
self.fsema.release_lock() self.fsema.release_lock()
if not self._empty(): if not self._empty():
self.esema.release_lock() self.esema.release_lock()
self.mutex.release_lock() self.mutex.release_lock()
return item return item
# Get an item from the queue if one is immediately available, # Get an item from the queue if one is immediately available,
# raise Empty if the queue is empty or temporarily unavailable # raise Empty if the queue is empty or temporarily unavailable
def get_nowait(self): def get_nowait(self):
"""Gets and returns an item from the queue. """Gets and returns an item from the queue.
Only gets an item if one is immediately available, Otherwise Only gets an item if one is immediately available, Otherwise
this raises the Empty exception if the queue is empty or this raises the Empty exception if the queue is empty or
temporarily unavailable. temporarily unavailable.
""" """
locked = self.esema.acquire_lock(0) locked = self.esema.acquire_lock(0)
self.mutex.acquire_lock() self.mutex.acquire_lock()
if self._empty(): if self._empty():
# The queue is empty -- we can't have esema # The queue is empty -- we can't have esema
self.mutex.release_lock() self.mutex.release_lock()
raise Empty raise Empty
if not locked: if not locked:
locked = self.esema.acquire_lock(0) locked = self.esema.acquire_lock(0)
if not locked: if not locked:
# Somebody else has esema # Somebody else has esema
# but we have mutex -- # but we have mutex --
# go out of their way # go out of their way
self.mutex.release_lock() self.mutex.release_lock()
raise Empty raise Empty
was_full = self._full() was_full = self._full()
item = self._get() item = self._get()
if was_full: if was_full:
self.fsema.release_lock() self.fsema.release_lock()
if not self._empty(): if not self._empty():
self.esema.release_lock() self.esema.release_lock()
self.mutex.release_lock() self.mutex.release_lock()
return item return item
# XXX Need to define put_nowait() as well. # XXX Need to define put_nowait() as well.
...@@ -110,26 +110,26 @@ class Queue: ...@@ -110,26 +110,26 @@ class Queue:
# Initialize the queue representation # Initialize the queue representation
def _init(self, maxsize): def _init(self, maxsize):
self.maxsize = maxsize self.maxsize = maxsize
self.queue = [] self.queue = []
def _qsize(self): def _qsize(self):
return len(self.queue) return len(self.queue)
# Check wheter the queue is empty # Check wheter the queue is empty
def _empty(self): def _empty(self):
return not self.queue return not self.queue
# Check whether the queue is full # Check whether the queue is full
def _full(self): def _full(self):
return self.maxsize > 0 and len(self.queue) == self.maxsize return self.maxsize > 0 and len(self.queue) == self.maxsize
# Put a new item in the queue # Put a new item in the queue
def _put(self, item): def _put(self, item):
self.queue.append(item) self.queue.append(item)
# Get an item from the queue # Get an item from the queue
def _get(self): def _get(self):
item = self.queue[0] item = self.queue[0]
del self.queue[0] del self.queue[0]
return item return item
...@@ -108,36 +108,36 @@ def convert(s, syntax=None): ...@@ -108,36 +108,36 @@ def convert(s, syntax=None):
""" """
table = mastertable.copy() table = mastertable.copy()
if syntax is None: if syntax is None:
syntax = regex.get_syntax() syntax = regex.get_syntax()
if syntax & RE_NO_BK_PARENS: if syntax & RE_NO_BK_PARENS:
del table[r'\('], table[r'\)'] del table[r'\('], table[r'\)']
del table['('], table[')'] del table['('], table[')']
if syntax & RE_NO_BK_VBAR: if syntax & RE_NO_BK_VBAR:
del table[r'\|'] del table[r'\|']
del table['|'] del table['|']
if syntax & RE_BK_PLUS_QM: if syntax & RE_BK_PLUS_QM:
table['+'] = r'\+' table['+'] = r'\+'
table['?'] = r'\?' table['?'] = r'\?'
table[r'\+'] = '+' table[r'\+'] = '+'
table[r'\?'] = '?' table[r'\?'] = '?'
if syntax & RE_NEWLINE_OR: if syntax & RE_NEWLINE_OR:
table['\n'] = '|' table['\n'] = '|'
res = "" res = ""
i = 0 i = 0
end = len(s) end = len(s)
while i < end: while i < end:
c = s[i] c = s[i]
i = i+1 i = i+1
if c == '\\': if c == '\\':
c = s[i] c = s[i]
i = i+1 i = i+1
key = '\\' + c key = '\\' + c
key = table.get(key, key) key = table.get(key, key)
res = res + key res = res + key
else: else:
c = table.get(c, c) c = table.get(c, c)
res = res + c res = res + c
return res return res
...@@ -155,21 +155,21 @@ def quote(s, quote=None): ...@@ -155,21 +155,21 @@ def quote(s, quote=None):
""" """
if quote is None: if quote is None:
q = "'" q = "'"
altq = "'" altq = "'"
if q in s and altq not in s: if q in s and altq not in s:
q = altq q = altq
else: else:
assert quote in ('"', "'") assert quote in ('"', "'")
q = quote q = quote
res = q res = q
for c in s: for c in s:
if c == q: c = '\\' + c if c == q: c = '\\' + c
elif c < ' ' or c > '~': c = "\\%03o" % ord(c) elif c < ' ' or c > '~': c = "\\%03o" % ord(c)
res = res + c res = res + c
res = res + q res = res + q
if '\\' in res: if '\\' in res:
res = 'r' + res res = 'r' + res
return res return res
...@@ -179,7 +179,7 @@ def main(): ...@@ -179,7 +179,7 @@ def main():
s = eval(sys.stdin.read()) s = eval(sys.stdin.read())
sys.stdout.write(quote(convert(s))) sys.stdout.write(quote(convert(s)))
if sys.stdout.isatty(): if sys.stdout.isatty():
sys.stdout.write("\n") sys.stdout.write("\n")
if __name__ == '__main__': if __name__ == '__main__':
......
...@@ -47,60 +47,60 @@ import __main__ ...@@ -47,60 +47,60 @@ import __main__
class Completer: class Completer:
def complete(self, text, state): def complete(self, text, state):
"""Return the next possible completion for 'text'. """Return the next possible completion for 'text'.
This is called successively with state == 0, 1, 2, ... until it This is called successively with state == 0, 1, 2, ... until it
returns None. The completion should begin with 'text'. returns None. The completion should begin with 'text'.
""" """
if state == 0: if state == 0:
if "." in text: if "." in text:
self.matches = self.attr_matches(text) self.matches = self.attr_matches(text)
else: else:
self.matches = self.global_matches(text) self.matches = self.global_matches(text)
return self.matches[state] return self.matches[state]
def global_matches(self, text): def global_matches(self, text):
"""Compute matches when text is a simple name. """Compute matches when text is a simple name.
Return a list of all keywords, built-in functions and names Return a list of all keywords, built-in functions and names
currently defines in __main__ that match. currently defines in __main__ that match.
""" """
import keyword import keyword
matches = [] matches = []
n = len(text) n = len(text)
for list in [keyword.kwlist, for list in [keyword.kwlist,
__builtin__.__dict__.keys(), __builtin__.__dict__.keys(),
__main__.__dict__.keys()]: __main__.__dict__.keys()]:
for word in list: for word in list:
if word[:n] == text: if word[:n] == text:
matches.append(word) matches.append(word)
return matches return matches
def attr_matches(self, text): def attr_matches(self, text):
"""Compute matches when text contains a dot. """Compute matches when text contains a dot.
Assuming the text is of the form NAME.NAME....[NAME], and is Assuming the text is of the form NAME.NAME....[NAME], and is
evaluabable in the globals of __main__, it will be evaluated evaluabable in the globals of __main__, it will be evaluated
and its attributes (as revealed by dir()) are used as possible and its attributes (as revealed by dir()) are used as possible
completions. completions.
WARNING: this can still invoke arbitrary C code, if an object WARNING: this can still invoke arbitrary C code, if an object
with a __getattr__ hook is evaluated. with a __getattr__ hook is evaluated.
""" """
import re import re
m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text) m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text)
if not m: if not m:
return return
expr, attr = m.group(1, 3) expr, attr = m.group(1, 3)
words = dir(eval(expr, __main__.__dict__)) words = dir(eval(expr, __main__.__dict__))
matches = [] matches = []
n = len(attr) n = len(attr)
for word in words: for word in words:
if word[:n] == attr: if word[:n] == attr:
matches.append("%s.%s" % (expr, word)) matches.append("%s.%s" % (expr, word))
return matches return matches
readline.set_completer(Completer().complete) readline.set_completer(Completer().complete)
...@@ -36,119 +36,119 @@ class SimpleHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): ...@@ -36,119 +36,119 @@ class SimpleHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
server_version = "SimpleHTTP/" + __version__ server_version = "SimpleHTTP/" + __version__
def do_GET(self): def do_GET(self):
"""Serve a GET request.""" """Serve a GET request."""
f = self.send_head() f = self.send_head()
if f: if f:
self.copyfile(f, self.wfile) self.copyfile(f, self.wfile)
f.close() f.close()
def do_HEAD(self): def do_HEAD(self):
"""Serve a HEAD request.""" """Serve a HEAD request."""
f = self.send_head() f = self.send_head()
if f: if f:
f.close() f.close()
def send_head(self): def send_head(self):
"""Common code for GET and HEAD commands. """Common code for GET and HEAD commands.
This sends the response code and MIME headers. This sends the response code and MIME headers.
Return value is either a file object (which has to be copied Return value is either a file object (which has to be copied
to the outputfile by the caller unless the command was HEAD, to the outputfile by the caller unless the command was HEAD,
and must be closed by the caller under all circumstances), or and must be closed by the caller under all circumstances), or
None, in which case the caller has nothing further to do. None, in which case the caller has nothing further to do.
""" """
path = self.translate_path(self.path) path = self.translate_path(self.path)
if os.path.isdir(path): if os.path.isdir(path):
self.send_error(403, "Directory listing not supported") self.send_error(403, "Directory listing not supported")
return None return None
try: try:
f = open(path) f = open(path)
except IOError: except IOError:
self.send_error(404, "File not found") self.send_error(404, "File not found")
return None return None
self.send_response(200) self.send_response(200)
self.send_header("Content-type", self.guess_type(path)) self.send_header("Content-type", self.guess_type(path))
self.end_headers() self.end_headers()
return f return f
def translate_path(self, path): def translate_path(self, path):
"""Translate a /-separated PATH to the local filename syntax. """Translate a /-separated PATH to the local filename syntax.
Components that mean special things to the local file system Components that mean special things to the local file system
(e.g. drive or directory names) are ignored. (XXX They should (e.g. drive or directory names) are ignored. (XXX They should
probably be diagnosed.) probably be diagnosed.)
""" """
path = posixpath.normpath(path) path = posixpath.normpath(path)
words = string.splitfields(path, '/') words = string.splitfields(path, '/')
words = filter(None, words) words = filter(None, words)
path = os.getcwd() path = os.getcwd()
for word in words: for word in words:
drive, word = os.path.splitdrive(word) drive, word = os.path.splitdrive(word)
head, word = os.path.split(word) head, word = os.path.split(word)
if word in (os.curdir, os.pardir): continue if word in (os.curdir, os.pardir): continue
path = os.path.join(path, word) path = os.path.join(path, word)
return path return path
def copyfile(self, source, outputfile): def copyfile(self, source, outputfile):
"""Copy all data between two file objects. """Copy all data between two file objects.
The SOURCE argument is a file object open for reading The SOURCE argument is a file object open for reading
(or anything with a read() method) and the DESTINATION (or anything with a read() method) and the DESTINATION
argument is a file object open for writing (or argument is a file object open for writing (or
anything with a write() method). anything with a write() method).
The only reason for overriding this would be to change The only reason for overriding this would be to change
the block size or perhaps to replace newlines by CRLF the block size or perhaps to replace newlines by CRLF
-- note however that this the default server uses this -- note however that this the default server uses this
to copy binary data as well. to copy binary data as well.
""" """
BLOCKSIZE = 8192 BLOCKSIZE = 8192
while 1: while 1:
data = source.read(BLOCKSIZE) data = source.read(BLOCKSIZE)
if not data: break if not data: break
outputfile.write(data) outputfile.write(data)
def guess_type(self, path): def guess_type(self, path):
"""Guess the type of a file. """Guess the type of a file.
Argument is a PATH (a filename). Argument is a PATH (a filename).
Return value is a string of the form type/subtype, Return value is a string of the form type/subtype,
usable for a MIME Content-type header. usable for a MIME Content-type header.
The default implementation looks the file's extension The default implementation looks the file's extension
up in the table self.extensions_map, using text/plain up in the table self.extensions_map, using text/plain
as a default; however it would be permissible (if as a default; however it would be permissible (if
slow) to look inside the data to make a better guess. slow) to look inside the data to make a better guess.
""" """
base, ext = posixpath.splitext(path) base, ext = posixpath.splitext(path)
if self.extensions_map.has_key(ext): if self.extensions_map.has_key(ext):
return self.extensions_map[ext] return self.extensions_map[ext]
ext = string.lower(ext) ext = string.lower(ext)
if self.extensions_map.has_key(ext): if self.extensions_map.has_key(ext):
return self.extensions_map[ext] return self.extensions_map[ext]
else: else:
return self.extensions_map[''] return self.extensions_map['']
extensions_map = { extensions_map = {
'': 'text/plain', # Default, *must* be present '': 'text/plain', # Default, *must* be present
'.html': 'text/html', '.html': 'text/html',
'.htm': 'text/html', '.htm': 'text/html',
'.gif': 'image/gif', '.gif': 'image/gif',
'.jpg': 'image/jpeg', '.jpg': 'image/jpeg',
'.jpeg': 'image/jpeg', '.jpeg': 'image/jpeg',
} }
def test(HandlerClass = SimpleHTTPRequestHandler, def test(HandlerClass = SimpleHTTPRequestHandler,
ServerClass = SocketServer.TCPServer): ServerClass = SocketServer.TCPServer):
BaseHTTPServer.test(HandlerClass, ServerClass) BaseHTTPServer.test(HandlerClass, ServerClass)
......
...@@ -3,19 +3,19 @@ ...@@ -3,19 +3,19 @@
This module tries to capture the various aspects of defining a server: This module tries to capture the various aspects of defining a server:
- address family: - address family:
- AF_INET: IP (Internet Protocol) sockets (default) - AF_INET: IP (Internet Protocol) sockets (default)
- AF_UNIX: Unix domain sockets - AF_UNIX: Unix domain sockets
- others, e.g. AF_DECNET are conceivable (see <socket.h> - others, e.g. AF_DECNET are conceivable (see <socket.h>
- socket type: - socket type:
- SOCK_STREAM (reliable stream, e.g. TCP) - SOCK_STREAM (reliable stream, e.g. TCP)
- SOCK_DGRAM (datagrams, e.g. UDP) - SOCK_DGRAM (datagrams, e.g. UDP)
- client address verification before further looking at the request - client address verification before further looking at the request
(This is actually a hook for any processing that needs to look (This is actually a hook for any processing that needs to look
at the request before anything else, e.g. logging) at the request before anything else, e.g. logging)
- how to handle multiple requests: - how to handle multiple requests:
- synchronous (one request is handled at a time) - synchronous (one request is handled at a time)
- forking (each request is handled by a new process) - forking (each request is handled by a new process)
- threading (each request is handled by a new thread) - threading (each request is handled by a new thread)
The classes in this module favor the server type that is simplest to The classes in this module favor the server type that is simplest to
write: a synchronous TCP/IP server. This is bad class design, but write: a synchronous TCP/IP server. This is bad class design, but
...@@ -25,14 +25,14 @@ slows down method lookups.) ...@@ -25,14 +25,14 @@ slows down method lookups.)
There are four classes in an inheritance diagram that represent There are four classes in an inheritance diagram that represent
synchronous servers of four types: synchronous servers of four types:
+-----------+ +------------------+ +-----------+ +------------------+
| TCPServer |------->| UnixStreamServer | | TCPServer |------->| UnixStreamServer |
+-----------+ +------------------+ +-----------+ +------------------+
| |
v v
+-----------+ +--------------------+ +-----------+ +--------------------+
| UDPServer |------->| UnixDatagramServer | | UDPServer |------->| UnixDatagramServer |
+-----------+ +--------------------+ +-----------+ +--------------------+
Note that UnixDatagramServer derives from UDPServer, not from Note that UnixDatagramServer derives from UDPServer, not from
UnixStreamServer -- the only difference between an IP and a Unix UnixStreamServer -- the only difference between an IP and a Unix
...@@ -43,7 +43,7 @@ Forking and threading versions of each type of server can be created ...@@ -43,7 +43,7 @@ Forking and threading versions of each type of server can be created
using the ForkingServer and ThreadingServer mix-in classes. For using the ForkingServer and ThreadingServer mix-in classes. For
instance, a threading UDP server class is created as follows: instance, a threading UDP server class is created as follows:
class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass
The Mix-in class must come first, since it overrides a method defined The Mix-in class must come first, since it overrides a method defined
in UDPServer! in UDPServer!
...@@ -119,8 +119,8 @@ class TCPServer: ...@@ -119,8 +119,8 @@ class TCPServer:
- __init__(server_address, RequestHandlerClass) - __init__(server_address, RequestHandlerClass)
- serve_forever() - serve_forever()
- handle_request() # if you don't use serve_forever() - handle_request() # if you don't use serve_forever()
- fileno() -> int # for select() - fileno() -> int # for select()
Methods that may be overridden: Methods that may be overridden:
...@@ -157,42 +157,42 @@ class TCPServer: ...@@ -157,42 +157,42 @@ class TCPServer:
request_queue_size = 5 request_queue_size = 5
def __init__(self, server_address, RequestHandlerClass): def __init__(self, server_address, RequestHandlerClass):
"""Constructor. May be extended, do not override.""" """Constructor. May be extended, do not override."""
self.server_address = server_address self.server_address = server_address
self.RequestHandlerClass = RequestHandlerClass self.RequestHandlerClass = RequestHandlerClass
self.socket = socket.socket(self.address_family, self.socket = socket.socket(self.address_family,
self.socket_type) self.socket_type)
self.server_bind() self.server_bind()
self.server_activate() self.server_activate()
def server_bind(self): def server_bind(self):
"""Called by constructor to bind the socket. """Called by constructor to bind the socket.
May be overridden. May be overridden.
""" """
self.socket.bind(self.server_address) self.socket.bind(self.server_address)
def server_activate(self): def server_activate(self):
"""Called by constructor to activate the server. """Called by constructor to activate the server.
May be overridden. May be overridden.
""" """
self.socket.listen(self.request_queue_size) self.socket.listen(self.request_queue_size)
def fileno(self): def fileno(self):
"""Return socket file number. """Return socket file number.
Interface required by select(). Interface required by select().
""" """
return self.socket.fileno() return self.socket.fileno()
def serve_forever(self): def serve_forever(self):
"""Handle one request at a time until doomsday.""" """Handle one request at a time until doomsday."""
while 1: while 1:
self.handle_request() self.handle_request()
# The distinction between handling, getting, processing and # The distinction between handling, getting, processing and
# finishing a request is fairly arbitrary. Remember: # finishing a request is fairly arbitrary. Remember:
...@@ -206,54 +206,54 @@ class TCPServer: ...@@ -206,54 +206,54 @@ class TCPServer:
# this constructor will handle the request all by itself # this constructor will handle the request all by itself
def handle_request(self): def handle_request(self):
"""Handle one request, possibly blocking.""" """Handle one request, possibly blocking."""
request, client_address = self.get_request() request, client_address = self.get_request()
if self.verify_request(request, client_address): if self.verify_request(request, client_address):
try: try:
self.process_request(request, client_address) self.process_request(request, client_address)
except: except:
self.handle_error(request, client_address) self.handle_error(request, client_address)
def get_request(self): def get_request(self):
"""Get the request and client address from the socket. """Get the request and client address from the socket.
May be overridden. May be overridden.
""" """
return self.socket.accept() return self.socket.accept()
def verify_request(self, request, client_address): def verify_request(self, request, client_address):
"""Verify the request. May be overridden. """Verify the request. May be overridden.
Return true if we should proceed with this request. Return true if we should proceed with this request.
""" """
return 1 return 1
def process_request(self, request, client_address): def process_request(self, request, client_address):
"""Call finish_request. """Call finish_request.
Overridden by ForkingMixIn and ThreadingMixIn. Overridden by ForkingMixIn and ThreadingMixIn.
""" """
self.finish_request(request, client_address) self.finish_request(request, client_address)
def finish_request(self, request, client_address): def finish_request(self, request, client_address):
"""Finish one request by instantiating RequestHandlerClass.""" """Finish one request by instantiating RequestHandlerClass."""
self.RequestHandlerClass(request, client_address, self) self.RequestHandlerClass(request, client_address, self)
def handle_error(self, request, client_address): def handle_error(self, request, client_address):
"""Handle an error gracefully. May be overridden. """Handle an error gracefully. May be overridden.
The default is to print a traceback and continue. The default is to print a traceback and continue.
""" """
print '-'*40 print '-'*40
print 'Exception happened during processing of request from', print 'Exception happened during processing of request from',
print client_address print client_address
import traceback import traceback
traceback.print_exc() traceback.print_exc()
print '-'*40 print '-'*40
class UDPServer(TCPServer): class UDPServer(TCPServer):
...@@ -265,19 +265,19 @@ class UDPServer(TCPServer): ...@@ -265,19 +265,19 @@ class UDPServer(TCPServer):
max_packet_size = 8192 max_packet_size = 8192
def get_request(self): def get_request(self):
return self.socket.recvfrom(self.max_packet_size) return self.socket.recvfrom(self.max_packet_size)
if hasattr(socket, 'AF_UNIX'): if hasattr(socket, 'AF_UNIX'):
class UnixStreamServer(TCPServer): class UnixStreamServer(TCPServer):
address_family = socket.AF_UNIX address_family = socket.AF_UNIX
class UnixDatagramServer(UDPServer): class UnixDatagramServer(UDPServer):
address_family = socket.AF_UNIX address_family = socket.AF_UNIX
class ForkingMixIn: class ForkingMixIn:
...@@ -287,34 +287,34 @@ class ForkingMixIn: ...@@ -287,34 +287,34 @@ class ForkingMixIn:
active_children = None active_children = None
def collect_children(self): def collect_children(self):
"""Internal routine to wait for died children.""" """Internal routine to wait for died children."""
while self.active_children: while self.active_children:
pid, status = os.waitpid(0, os.WNOHANG) pid, status = os.waitpid(0, os.WNOHANG)
if not pid: break if not pid: break
self.active_children.remove(pid) self.active_children.remove(pid)
def process_request(self, request, client_address): def process_request(self, request, client_address):
"""Fork a new subprocess to process the request.""" """Fork a new subprocess to process the request."""
self.collect_children() self.collect_children()
pid = os.fork() pid = os.fork()
if pid: if pid:
# Parent process # Parent process
if self.active_children is None: if self.active_children is None:
self.active_children = [] self.active_children = []
self.active_children.append(pid) self.active_children.append(pid)
return return
else: else:
# Child process. # Child process.
# This must never return, hence os._exit()! # This must never return, hence os._exit()!
try: try:
self.finish_request(request, client_address) self.finish_request(request, client_address)
os._exit(0) os._exit(0)
except: except:
try: try:
self.handle_error(request, self.handle_error(request,
client_address) client_address)
finally: finally:
os._exit(1) os._exit(1)
class ThreadingMixIn: class ThreadingMixIn:
...@@ -322,10 +322,10 @@ class ThreadingMixIn: ...@@ -322,10 +322,10 @@ class ThreadingMixIn:
"""Mix-in class to handle each request in a new thread.""" """Mix-in class to handle each request in a new thread."""
def process_request(self, request, client_address): def process_request(self, request, client_address):
"""Start a new thread to process the request.""" """Start a new thread to process the request."""
import thread import thread
thread.start_new_thread(self.finish_request, thread.start_new_thread(self.finish_request,
(request, client_address)) (request, client_address))
class ForkingUDPServer(ForkingMixIn, UDPServer): pass class ForkingUDPServer(ForkingMixIn, UDPServer): pass
...@@ -354,27 +354,27 @@ class BaseRequestHandler: ...@@ -354,27 +354,27 @@ class BaseRequestHandler:
""" """
def __init__(self, request, client_address, server): def __init__(self, request, client_address, server):
self.request = request self.request = request
self.client_address = client_address self.client_address = client_address
self.server = server self.server = server
try: try:
self.setup() self.setup()
self.handle() self.handle()
self.finish() self.finish()
finally: finally:
sys.exc_traceback = None # Help garbage collection sys.exc_traceback = None # Help garbage collection
def setup(self): def setup(self):
pass pass
def __del__(self): def __del__(self):
pass pass
def handle(self): def handle(self):
pass pass
def finish(self): def finish(self):
pass pass
# The following two classes make it possible to use the same service # The following two classes make it possible to use the same service
...@@ -390,12 +390,12 @@ class StreamRequestHandler(BaseRequestHandler): ...@@ -390,12 +390,12 @@ class StreamRequestHandler(BaseRequestHandler):
"""Define self.rfile and self.wfile for stream sockets.""" """Define self.rfile and self.wfile for stream sockets."""
def setup(self): def setup(self):
self.connection = self.request self.connection = self.request
self.rfile = self.connection.makefile('rb', 0) self.rfile = self.connection.makefile('rb', 0)
self.wfile = self.connection.makefile('wb', 0) self.wfile = self.connection.makefile('wb', 0)
def finish(self): def finish(self):
self.wfile.flush() self.wfile.flush()
class DatagramRequestHandler(BaseRequestHandler): class DatagramRequestHandler(BaseRequestHandler):
...@@ -403,10 +403,10 @@ class DatagramRequestHandler(BaseRequestHandler): ...@@ -403,10 +403,10 @@ class DatagramRequestHandler(BaseRequestHandler):
"""Define self.rfile and self.wfile for datagram sockets.""" """Define self.rfile and self.wfile for datagram sockets."""
def setup(self): def setup(self):
import StringIO import StringIO
self.packet, self.socket = self.request self.packet, self.socket = self.request
self.rfile = StringIO.StringIO(self.packet) self.rfile = StringIO.StringIO(self.packet)
self.wfile = StringIO.StringIO(self.packet) self.wfile = StringIO.StringIO(self.packet)
def finish(self): def finish(self):
self.socket.send(self.wfile.getvalue()) self.socket.send(self.wfile.getvalue())
...@@ -76,7 +76,7 @@ class Telnet: ...@@ -76,7 +76,7 @@ class Telnet:
read_until(expected, [timeout]) read_until(expected, [timeout])
Read until the expected string has been seen, or a timeout is Read until the expected string has been seen, or a timeout is
hit (default is no timeout); may block. hit (default is no timeout); may block.
read_all() read_all()
Read all data until EOF; may block. Read all data until EOF; may block.
...@@ -86,360 +86,362 @@ class Telnet: ...@@ -86,360 +86,362 @@ class Telnet:
read_very_eager() read_very_eager()
Read all data available already queued or on the socket, Read all data available already queued or on the socket,
without blocking. without blocking.
read_eager() read_eager()
Read either data already queued or some data available on the Read either data already queued or some data available on the
socket, without blocking. socket, without blocking.
read_lazy() read_lazy()
Read all data in the raw queue (processing it first), without Read all data in the raw queue (processing it first), without
doing any socket I/O. doing any socket I/O.
read_very_lazy() read_very_lazy()
Reads all data in the cooked queue, without doing any socket Reads all data in the cooked queue, without doing any socket
I/O. I/O.
""" """
def __init__(self, host=None, port=0): def __init__(self, host=None, port=0):
"""Constructor. """Constructor.
When called without arguments, create an unconnected instance. When called without arguments, create an unconnected instance.
With a hostname argument, it connects the instance; a port With a hostname argument, it connects the instance; a port
number is optional. number is optional.
""" """
self.debuglevel = DEBUGLEVEL self.debuglevel = DEBUGLEVEL
self.host = host self.host = host
self.port = port self.port = port
self.sock = None self.sock = None
self.rawq = '' self.rawq = ''
self.irawq = 0 self.irawq = 0
self.cookedq = '' self.cookedq = ''
self.eof = 0 self.eof = 0
if host: if host:
self.open(host, port) self.open(host, port)
def open(self, host, port=0): def open(self, host, port=0):
"""Connect to a host. """Connect to a host.
The optional second argument is the port number, which The optional second argument is the port number, which
defaults to the standard telnet port (23). defaults to the standard telnet port (23).
Don't try to reopen an already connected instance. Don't try to reopen an already connected instance.
""" """
self.eof = 0 self.eof = 0
if not port: if not port:
port = TELNET_PORT port = TELNET_PORT
self.host = host self.host = host
self.port = port self.port = port
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect((self.host, self.port)) self.sock.connect((self.host, self.port))
def __del__(self): def __del__(self):
"""Destructor -- close the connection.""" """Destructor -- close the connection."""
self.close() self.close()
def msg(self, msg, *args): def msg(self, msg, *args):
"""Print a debug message, when the debug level is > 0. """Print a debug message, when the debug level is > 0.
If extra arguments are present, they are substituted in the If extra arguments are present, they are substituted in the
message using the standard string formatting operator. message using the standard string formatting operator.
""" """
if self.debuglevel > 0: if self.debuglevel > 0:
print 'Telnet(%s,%d):' % (self.host, self.port), print 'Telnet(%s,%d):' % (self.host, self.port),
if args: if args:
print msg % args print msg % args
else: else:
print msg print msg
def set_debuglevel(self, debuglevel): def set_debuglevel(self, debuglevel):
"""Set the debug level. """Set the debug level.
The higher it is, the more debug output you get (on sys.stdout). The higher it is, the more debug output you get (on sys.stdout).
""" """
self.debuglevel = debuglevel self.debuglevel = debuglevel
def close(self): def close(self):
"""Close the connection.""" """Close the connection."""
if self.sock: if self.sock:
self.sock.close() self.sock.close()
self.sock = 0 self.sock = 0
self.eof = 1 self.eof = 1
def get_socket(self): def get_socket(self):
"""Return the socket object used internally.""" """Return the socket object used internally."""
return self.sock return self.sock
def fileno(self): def fileno(self):
"""Return the fileno() of the socket object used internally.""" """Return the fileno() of the socket object used internally."""
return self.sock.fileno() return self.sock.fileno()
def write(self, buffer): def write(self, buffer):
"""Write a string to the socket, doubling any IAC characters. """Write a string to the socket, doubling any IAC characters.
Can block if the connection is blocked. May raise Can block if the connection is blocked. May raise
socket.error if the connection is closed. socket.error if the connection is closed.
""" """
if IAC in buffer: if IAC in buffer:
buffer = string.replace(buffer, IAC, IAC+IAC) buffer = string.replace(buffer, IAC, IAC+IAC)
self.sock.send(buffer) self.msg("send %s", `buffer`)
self.sock.send(buffer)
def read_until(self, match, timeout=None): def read_until(self, match, timeout=None):
"""Read until a given string is encountered or until timeout. """Read until a given string is encountered or until timeout.
When no match is found, return whatever is available instead, When no match is found, return whatever is available instead,
possibly the empty string. Raise EOFError if the connection possibly the empty string. Raise EOFError if the connection
is closed and no cooked data is available. is closed and no cooked data is available.
""" """
n = len(match) n = len(match)
self.process_rawq() self.process_rawq()
i = string.find(self.cookedq, match) i = string.find(self.cookedq, match)
if i >= 0: if i >= 0:
i = i+n i = i+n
buf = self.cookedq[:i] buf = self.cookedq[:i]
self.cookedq = self.cookedq[i:] self.cookedq = self.cookedq[i:]
return buf return buf
s_reply = ([self], [], []) s_reply = ([self], [], [])
s_args = s_reply s_args = s_reply
if timeout is not None: if timeout is not None:
s_args = s_args + (timeout,) s_args = s_args + (timeout,)
while not self.eof and apply(select.select, s_args) == s_reply: while not self.eof and apply(select.select, s_args) == s_reply:
i = max(0, len(self.cookedq)-n) i = max(0, len(self.cookedq)-n)
self.fill_rawq() self.fill_rawq()
self.process_rawq() self.process_rawq()
i = string.find(self.cookedq, match, i) i = string.find(self.cookedq, match, i)
if i >= 0: if i >= 0:
i = i+n i = i+n
buf = self.cookedq[:i] buf = self.cookedq[:i]
self.cookedq = self.cookedq[i:] self.cookedq = self.cookedq[i:]
return buf return buf
return self.read_very_lazy() return self.read_very_lazy()
def read_all(self): def read_all(self):
"""Read all data until EOF; block until connection closed.""" """Read all data until EOF; block until connection closed."""
self.process_rawq() self.process_rawq()
while not self.eof: while not self.eof:
self.fill_rawq() self.fill_rawq()
self.process_rawq() self.process_rawq()
buf = self.cookedq buf = self.cookedq
self.cookedq = '' self.cookedq = ''
return buf return buf
def read_some(self): def read_some(self):
"""Read at least one byte of cooked data unless EOF is hit. """Read at least one byte of cooked data unless EOF is hit.
Return '' if EOF is hit. Block if no data is immediately Return '' if EOF is hit. Block if no data is immediately
available. available.
""" """
self.process_rawq() self.process_rawq()
while not self.cookedq and not self.eof: while not self.cookedq and not self.eof:
self.fill_rawq() self.fill_rawq()
self.process_rawq() self.process_rawq()
buf = self.cookedq buf = self.cookedq
self.cookedq = '' self.cookedq = ''
return buf return buf
def read_very_eager(self): def read_very_eager(self):
"""Read everything that's possible without blocking in I/O (eager). """Read everything that's possible without blocking in I/O (eager).
Raise EOFError if connection closed and no cooked data Raise EOFError if connection closed and no cooked data
available. Return '' if no cooked data available otherwise. available. Return '' if no cooked data available otherwise.
Don't block unless in the midst of an IAC sequence. Don't block unless in the midst of an IAC sequence.
""" """
self.process_rawq() self.process_rawq()
while not self.eof and self.sock_avail(): while not self.eof and self.sock_avail():
self.fill_rawq() self.fill_rawq()
self.process_rawq() self.process_rawq()
return self.read_very_lazy() return self.read_very_lazy()
def read_eager(self): def read_eager(self):
"""Read readily available data. """Read readily available data.
Raise EOFError if connection closed and no cooked data Raise EOFError if connection closed and no cooked data
available. Return '' if no cooked data available otherwise. available. Return '' if no cooked data available otherwise.
Don't block unless in the midst of an IAC sequence. Don't block unless in the midst of an IAC sequence.
""" """
self.process_rawq() self.process_rawq()
while not self.cookedq and not self.eof and self.sock_avail(): while not self.cookedq and not self.eof and self.sock_avail():
self.fill_rawq() self.fill_rawq()
self.process_rawq() self.process_rawq()
return self.read_very_lazy() return self.read_very_lazy()
def read_lazy(self): def read_lazy(self):
"""Process and return data that's already in the queues (lazy). """Process and return data that's already in the queues (lazy).
Raise EOFError if connection closed and no data available. Raise EOFError if connection closed and no data available.
Return '' if no cooked data available otherwise. Don't block Return '' if no cooked data available otherwise. Don't block
unless in the midst of an IAC sequence. unless in the midst of an IAC sequence.
""" """
self.process_rawq() self.process_rawq()
return self.read_very_lazy() return self.read_very_lazy()
def read_very_lazy(self): def read_very_lazy(self):
"""Return any data available in the cooked queue (very lazy). """Return any data available in the cooked queue (very lazy).
Raise EOFError if connection closed and no data available. Raise EOFError if connection closed and no data available.
Return '' if no cooked data available otherwise. Don't block. Return '' if no cooked data available otherwise. Don't block.
""" """
buf = self.cookedq buf = self.cookedq
self.cookedq = '' self.cookedq = ''
if not buf and self.eof and not self.rawq: if not buf and self.eof and not self.rawq:
raise EOFError, 'telnet connection closed' raise EOFError, 'telnet connection closed'
return buf return buf
def process_rawq(self): def process_rawq(self):
"""Transfer from raw queue to cooked queue. """Transfer from raw queue to cooked queue.
Set self.eof when connection is closed. Don't block unless in Set self.eof when connection is closed. Don't block unless in
the midst of an IAC sequence. the midst of an IAC sequence.
""" """
buf = '' buf = ''
try: try:
while self.rawq: while self.rawq:
c = self.rawq_getchar() c = self.rawq_getchar()
if c == theNULL: if c == theNULL:
continue continue
if c == "\021": if c == "\021":
continue continue
if c != IAC: if c != IAC:
buf = buf + c buf = buf + c
continue continue
c = self.rawq_getchar() c = self.rawq_getchar()
if c == IAC: if c == IAC:
buf = buf + c buf = buf + c
elif c in (DO, DONT): elif c in (DO, DONT):
opt = self.rawq_getchar() opt = self.rawq_getchar()
self.msg('IAC %s %d', c == DO and 'DO' or 'DONT', ord(c)) self.msg('IAC %s %d', c == DO and 'DO' or 'DONT', ord(c))
self.sock.send(IAC + WONT + opt) self.sock.send(IAC + WONT + opt)
elif c in (WILL, WONT): elif c in (WILL, WONT):
opt = self.rawq_getchar() opt = self.rawq_getchar()
self.msg('IAC %s %d', self.msg('IAC %s %d',
c == WILL and 'WILL' or 'WONT', ord(c)) c == WILL and 'WILL' or 'WONT', ord(c))
else: else:
self.msg('IAC %s not recognized' % `c`) self.msg('IAC %s not recognized' % `c`)
except EOFError: # raised by self.rawq_getchar() except EOFError: # raised by self.rawq_getchar()
pass pass
self.cookedq = self.cookedq + buf self.cookedq = self.cookedq + buf
def rawq_getchar(self): def rawq_getchar(self):
"""Get next char from raw queue. """Get next char from raw queue.
Block if no data is immediately available. Raise EOFError Block if no data is immediately available. Raise EOFError
when connection is closed. when connection is closed.
""" """
if not self.rawq: if not self.rawq:
self.fill_rawq() self.fill_rawq()
if self.eof: if self.eof:
raise EOFError raise EOFError
c = self.rawq[self.irawq] c = self.rawq[self.irawq]
self.irawq = self.irawq + 1 self.irawq = self.irawq + 1
if self.irawq >= len(self.rawq): if self.irawq >= len(self.rawq):
self.rawq = '' self.rawq = ''
self.irawq = 0 self.irawq = 0
return c return c
def fill_rawq(self): def fill_rawq(self):
"""Fill raw queue from exactly one recv() system call. """Fill raw queue from exactly one recv() system call.
Block if no data is immediately available. Set self.eof when Block if no data is immediately available. Set self.eof when
connection is closed. connection is closed.
""" """
if self.irawq >= len(self.rawq): if self.irawq >= len(self.rawq):
self.rawq = '' self.rawq = ''
self.irawq = 0 self.irawq = 0
# The buffer size should be fairly small so as to avoid quadratic # The buffer size should be fairly small so as to avoid quadratic
# behavior in process_rawq() above # behavior in process_rawq() above
buf = self.sock.recv(50) buf = self.sock.recv(50)
self.eof = (not buf) self.msg("recv %s", `buf`)
self.rawq = self.rawq + buf self.eof = (not buf)
self.rawq = self.rawq + buf
def sock_avail(self): def sock_avail(self):
"""Test whether data is available on the socket.""" """Test whether data is available on the socket."""
return select.select([self], [], [], 0) == ([self], [], []) return select.select([self], [], [], 0) == ([self], [], [])
def interact(self): def interact(self):
"""Interaction function, emulates a very dumb telnet client.""" """Interaction function, emulates a very dumb telnet client."""
while 1: while 1:
rfd, wfd, xfd = select.select([self, sys.stdin], [], []) rfd, wfd, xfd = select.select([self, sys.stdin], [], [])
if self in rfd: if self in rfd:
try: try:
text = self.read_eager() text = self.read_eager()
except EOFError: except EOFError:
print '*** Connection closed by remote host ***' print '*** Connection closed by remote host ***'
break break
if text: if text:
sys.stdout.write(text) sys.stdout.write(text)
sys.stdout.flush() sys.stdout.flush()
if sys.stdin in rfd: if sys.stdin in rfd:
line = sys.stdin.readline() line = sys.stdin.readline()
if not line: if not line:
break break
self.write(line) self.write(line)
def expect(self, list, timeout=None): def expect(self, list, timeout=None):
"""Read until one from a list of a regular expressions matches. """Read until one from a list of a regular expressions matches.
The first argument is a list of regular expressions, either The first argument is a list of regular expressions, either
compiled (re.RegexObject instances) or uncompiled (strings). compiled (re.RegexObject instances) or uncompiled (strings).
The optional second argument is a timeout, in seconds; default The optional second argument is a timeout, in seconds; default
is no timeout. is no timeout.
Return a tuple of three items: the index in the list of the Return a tuple of three items: the index in the list of the
first regular expression that matches; the match object first regular expression that matches; the match object
returned; and the text read up till and including the match. returned; and the text read up till and including the match.
If EOF is read and no text was read, raise EOFError. If EOF is read and no text was read, raise EOFError.
Otherwise, when nothing matches, return (-1, None, text) where Otherwise, when nothing matches, return (-1, None, text) where
text is the text received so far (may be the empty string if a text is the text received so far (may be the empty string if a
timeout happened). timeout happened).
If a regular expression ends with a greedy match (e.g. '.*') If a regular expression ends with a greedy match (e.g. '.*')
or if more than one expression can match the same input, the or if more than one expression can match the same input, the
results are undeterministic, and may depend on the I/O timing. results are undeterministic, and may depend on the I/O timing.
""" """
re = None re = None
list = list[:] list = list[:]
indices = range(len(list)) indices = range(len(list))
for i in indices: for i in indices:
if not hasattr(list[i], "search"): if not hasattr(list[i], "search"):
if not re: import re if not re: import re
list[i] = re.compile(list[i]) list[i] = re.compile(list[i])
while 1: while 1:
self.process_rawq() self.process_rawq()
for i in indices: for i in indices:
m = list[i].search(self.cookedq) m = list[i].search(self.cookedq)
if m: if m:
e = m.end() e = m.end()
text = self.cookedq[:e] text = self.cookedq[:e]
self.cookedq = self.cookedq[e:] self.cookedq = self.cookedq[e:]
return (i, m, text) return (i, m, text)
if self.eof: if self.eof:
break break
if timeout is not None: if timeout is not None:
r, w, x = select.select([self.fileno()], [], [], timeout) r, w, x = select.select([self.fileno()], [], [], timeout)
if not r: if not r:
break break
self.fill_rawq() self.fill_rawq()
text = self.read_very_lazy() text = self.read_very_lazy()
if not text and self.eof: if not text and self.eof:
raise EOFError raise EOFError
return (-1, None, text) return (-1, None, text)
def test(): def test():
...@@ -452,18 +454,18 @@ def test(): ...@@ -452,18 +454,18 @@ def test():
""" """
debuglevel = 0 debuglevel = 0
while sys.argv[1:] and sys.argv[1] == '-d': while sys.argv[1:] and sys.argv[1] == '-d':
debuglevel = debuglevel+1 debuglevel = debuglevel+1
del sys.argv[1] del sys.argv[1]
host = 'localhost' host = 'localhost'
if sys.argv[1:]: if sys.argv[1:]:
host = sys.argv[1] host = sys.argv[1]
port = 0 port = 0
if sys.argv[2:]: if sys.argv[2:]:
portstr = sys.argv[2] portstr = sys.argv[2]
try: try:
port = int(portstr) port = int(portstr)
except ValueError: except ValueError:
port = socket.getservbyname(portstr, 'tcp') port = socket.getservbyname(portstr, 'tcp')
tn = Telnet() tn = Telnet()
tn.set_debuglevel(debuglevel) tn.set_debuglevel(debuglevel)
tn.open(host, port) tn.open(host, port)
......
...@@ -10,50 +10,50 @@ def main(): ...@@ -10,50 +10,50 @@ def main():
testtype('c', 'c') testtype('c', 'c')
for type in (['b', 'h', 'i', 'l', 'f', 'd']): for type in (['b', 'h', 'i', 'l', 'f', 'd']):
testtype(type, 1) testtype(type, 1)
unlink(TESTFN) unlink(TESTFN)
def testtype(type, example): def testtype(type, example):
a = array.array(type) a = array.array(type)
a.append(example) a.append(example)
if verbose: if verbose:
print 40*'*' print 40*'*'
print 'array after append: ', a print 'array after append: ', a
a.typecode a.typecode
a.itemsize a.itemsize
if a.typecode in ('i', 'b', 'h', 'l'): if a.typecode in ('i', 'b', 'h', 'l'):
a.byteswap() a.byteswap()
if a.typecode == 'c': if a.typecode == 'c':
f = open(TESTFN, "w") f = open(TESTFN, "w")
f.write("The quick brown fox jumps over the lazy dog.\n") f.write("The quick brown fox jumps over the lazy dog.\n")
f.close() f.close()
f = open(TESTFN, 'r') f = open(TESTFN, 'r')
a.fromfile(f, 10) a.fromfile(f, 10)
f.close() f.close()
if verbose: if verbose:
print 'char array with 10 bytes of TESTFN appended: ', a print 'char array with 10 bytes of TESTFN appended: ', a
a.fromlist(['a', 'b', 'c']) a.fromlist(['a', 'b', 'c'])
if verbose: if verbose:
print 'char array with list appended: ', a print 'char array with list appended: ', a
a.insert(0, example) a.insert(0, example)
if verbose: if verbose:
print 'array of %s after inserting another:' % a.typecode, a print 'array of %s after inserting another:' % a.typecode, a
f = open(TESTFN, 'w') f = open(TESTFN, 'w')
a.tofile(f) a.tofile(f)
f.close() f.close()
a.tolist() a.tolist()
a.tostring() a.tostring()
if verbose: if verbose:
print 'array of %s converted to a list: ' % a.typecode, a.tolist() print 'array of %s converted to a list: ' % a.typecode, a.tolist()
if verbose: if verbose:
print 'array of %s converted to a string: ' \ print 'array of %s converted to a string: ' \
% a.typecode, `a.tostring()` % a.typecode, `a.tostring()`
main() main()
...@@ -7,166 +7,166 @@ def gendata1(): ...@@ -7,166 +7,166 @@ def gendata1():
def gendata2(): def gendata2():
if verbose: if verbose:
print 'getsample' print 'getsample'
if audioop.getsample('\0\1', 2, 0) == 1: if audioop.getsample('\0\1', 2, 0) == 1:
return '\0\0\0\1\0\2' return '\0\0\0\1\0\2'
else: else:
return '\0\0\1\0\2\0' return '\0\0\1\0\2\0'
def gendata4(): def gendata4():
if verbose: if verbose:
print 'getsample' print 'getsample'
if audioop.getsample('\0\0\0\1', 4, 0) == 1: if audioop.getsample('\0\0\0\1', 4, 0) == 1:
return '\0\0\0\0\0\0\0\1\0\0\0\2' return '\0\0\0\0\0\0\0\1\0\0\0\2'
else: else:
return '\0\0\0\0\1\0\0\0\2\0\0\0' return '\0\0\0\0\1\0\0\0\2\0\0\0'
def testmax(data): def testmax(data):
if verbose: if verbose:
print 'max' print 'max'
if audioop.max(data[0], 1) <> 2 or \ if audioop.max(data[0], 1) <> 2 or \
audioop.max(data[1], 2) <> 2 or \ audioop.max(data[1], 2) <> 2 or \
audioop.max(data[2], 4) <> 2: audioop.max(data[2], 4) <> 2:
return 0 return 0
return 1 return 1
def testminmax(data): def testminmax(data):
if verbose: if verbose:
print 'minmax' print 'minmax'
if audioop.minmax(data[0], 1) <> (0, 2) or \ if audioop.minmax(data[0], 1) <> (0, 2) or \
audioop.minmax(data[1], 2) <> (0, 2) or \ audioop.minmax(data[1], 2) <> (0, 2) or \
audioop.minmax(data[2], 4) <> (0, 2): audioop.minmax(data[2], 4) <> (0, 2):
return 0 return 0
return 1 return 1
def testmaxpp(data): def testmaxpp(data):
if verbose: if verbose:
print 'maxpp' print 'maxpp'
if audioop.maxpp(data[0], 1) <> 0 or \ if audioop.maxpp(data[0], 1) <> 0 or \
audioop.maxpp(data[1], 2) <> 0 or \ audioop.maxpp(data[1], 2) <> 0 or \
audioop.maxpp(data[2], 4) <> 0: audioop.maxpp(data[2], 4) <> 0:
return 0 return 0
return 1 return 1
def testavg(data): def testavg(data):
if verbose: if verbose:
print 'avg' print 'avg'
if audioop.avg(data[0], 1) <> 1 or \ if audioop.avg(data[0], 1) <> 1 or \
audioop.avg(data[1], 2) <> 1 or \ audioop.avg(data[1], 2) <> 1 or \
audioop.avg(data[2], 4) <> 1: audioop.avg(data[2], 4) <> 1:
return 0 return 0
return 1 return 1
def testavgpp(data): def testavgpp(data):
if verbose: if verbose:
print 'avgpp' print 'avgpp'
if audioop.avgpp(data[0], 1) <> 0 or \ if audioop.avgpp(data[0], 1) <> 0 or \
audioop.avgpp(data[1], 2) <> 0 or \ audioop.avgpp(data[1], 2) <> 0 or \
audioop.avgpp(data[2], 4) <> 0: audioop.avgpp(data[2], 4) <> 0:
return 0 return 0
return 1 return 1
def testrms(data): def testrms(data):
if audioop.rms(data[0], 1) <> 1 or \ if audioop.rms(data[0], 1) <> 1 or \
audioop.rms(data[1], 2) <> 1 or \ audioop.rms(data[1], 2) <> 1 or \
audioop.rms(data[2], 4) <> 1: audioop.rms(data[2], 4) <> 1:
return 0 return 0
return 1 return 1
def testcross(data): def testcross(data):
if verbose: if verbose:
print 'cross' print 'cross'
if audioop.cross(data[0], 1) <> 0 or \ if audioop.cross(data[0], 1) <> 0 or \
audioop.cross(data[1], 2) <> 0 or \ audioop.cross(data[1], 2) <> 0 or \
audioop.cross(data[2], 4) <> 0: audioop.cross(data[2], 4) <> 0:
return 0 return 0
return 1 return 1
def testadd(data): def testadd(data):
if verbose: if verbose:
print 'add' print 'add'
data2 = [] data2 = []
for d in data: for d in data:
str = '' str = ''
for s in d: for s in d:
str = str + chr(ord(s)*2) str = str + chr(ord(s)*2)
data2.append(str) data2.append(str)
if audioop.add(data[0], data[0], 1) <> data2[0] or \ if audioop.add(data[0], data[0], 1) <> data2[0] or \
audioop.add(data[1], data[1], 2) <> data2[1] or \ audioop.add(data[1], data[1], 2) <> data2[1] or \
audioop.add(data[2], data[2], 4) <> data2[2]: audioop.add(data[2], data[2], 4) <> data2[2]:
return 0 return 0
return 1 return 1
def testbias(data): def testbias(data):
if verbose: if verbose:
print 'bias' print 'bias'
# Note: this test assumes that avg() works # Note: this test assumes that avg() works
d1 = audioop.bias(data[0], 1, 100) d1 = audioop.bias(data[0], 1, 100)
d2 = audioop.bias(data[1], 2, 100) d2 = audioop.bias(data[1], 2, 100)
d4 = audioop.bias(data[2], 4, 100) d4 = audioop.bias(data[2], 4, 100)
if audioop.avg(d1, 1) <> 101 or \ if audioop.avg(d1, 1) <> 101 or \
audioop.avg(d2, 2) <> 101 or \ audioop.avg(d2, 2) <> 101 or \
audioop.avg(d4, 4) <> 101: audioop.avg(d4, 4) <> 101:
return 0 return 0
return 1 return 1
def testlin2lin(data): def testlin2lin(data):
if verbose: if verbose:
print 'lin2lin' print 'lin2lin'
# too simple: we test only the size # too simple: we test only the size
for d1 in data: for d1 in data:
for d2 in data: for d2 in data:
got = len(d1)/3 got = len(d1)/3
wtd = len(d2)/3 wtd = len(d2)/3
if len(audioop.lin2lin(d1, got, wtd)) <> len(d2): if len(audioop.lin2lin(d1, got, wtd)) <> len(d2):
return 0 return 0
return 1 return 1
def testadpcm2lin(data): def testadpcm2lin(data):
# Very cursory test # Very cursory test
if audioop.adpcm2lin('\0\0', 1, None) <> ('\0\0\0\0', (0,0)): if audioop.adpcm2lin('\0\0', 1, None) <> ('\0\0\0\0', (0,0)):
return 0 return 0
return 1 return 1
def testlin2adpcm(data): def testlin2adpcm(data):
if verbose: if verbose:
print 'lin2adpcm' print 'lin2adpcm'
# Very cursory test # Very cursory test
if audioop.lin2adpcm('\0\0\0\0', 1, None) <> ('\0\0', (0,0)): if audioop.lin2adpcm('\0\0\0\0', 1, None) <> ('\0\0', (0,0)):
return 0 return 0
return 1 return 1
def testlin2ulaw(data): def testlin2ulaw(data):
if verbose: if verbose:
print 'lin2ulaw' print 'lin2ulaw'
if audioop.lin2ulaw(data[0], 1) <> '\377\347\333' or \ if audioop.lin2ulaw(data[0], 1) <> '\377\347\333' or \
audioop.lin2ulaw(data[1], 2) <> '\377\377\377' or \ audioop.lin2ulaw(data[1], 2) <> '\377\377\377' or \
audioop.lin2ulaw(data[2], 4) <> '\377\377\377': audioop.lin2ulaw(data[2], 4) <> '\377\377\377':
return 0 return 0
return 1 return 1
def testulaw2lin(data): def testulaw2lin(data):
if verbose: if verbose:
print 'ulaw2lin' print 'ulaw2lin'
# Cursory # Cursory
d = audioop.lin2ulaw(data[0], 1) d = audioop.lin2ulaw(data[0], 1)
if audioop.ulaw2lin(d, 1) <> data[0]: if audioop.ulaw2lin(d, 1) <> data[0]:
return 0 return 0
return 1 return 1
def testmul(data): def testmul(data):
if verbose: if verbose:
print 'mul' print 'mul'
data2 = [] data2 = []
for d in data: for d in data:
str = '' str = ''
for s in d: for s in d:
str = str + chr(ord(s)*2) str = str + chr(ord(s)*2)
data2.append(str) data2.append(str)
if audioop.mul(data[0], 1, 2) <> data2[0] or \ if audioop.mul(data[0], 1, 2) <> data2[0] or \
audioop.mul(data[1],2, 2) <> data2[1] or \ audioop.mul(data[1],2, 2) <> data2[1] or \
audioop.mul(data[2], 4, 2) <> data2[2]: audioop.mul(data[2], 4, 2) <> data2[2]:
return 0 return 0
return 1 return 1
def testratecv(data): def testratecv(data):
...@@ -181,75 +181,75 @@ def testratecv(data): ...@@ -181,75 +181,75 @@ def testratecv(data):
def testreverse(data): def testreverse(data):
if verbose: if verbose:
print 'reverse' print 'reverse'
if audioop.reverse(data[0], 1) <> '\2\1\0': if audioop.reverse(data[0], 1) <> '\2\1\0':
return 0 return 0
return 1 return 1
def testtomono(data): def testtomono(data):
if verbose: if verbose:
print 'tomono' print 'tomono'
data2 = '' data2 = ''
for d in data[0]: for d in data[0]:
data2 = data2 + d + d data2 = data2 + d + d
if audioop.tomono(data2, 1, 0.5, 0.5) <> data[0]: if audioop.tomono(data2, 1, 0.5, 0.5) <> data[0]:
return 0 return 0
return 1 return 1
def testtostereo(data): def testtostereo(data):
if verbose: if verbose:
print 'tostereo' print 'tostereo'
data2 = '' data2 = ''
for d in data[0]: for d in data[0]:
data2 = data2 + d + d data2 = data2 + d + d
if audioop.tostereo(data[0], 1, 1, 1) <> data2: if audioop.tostereo(data[0], 1, 1, 1) <> data2:
return 0 return 0
return 1 return 1
def testfindfactor(data): def testfindfactor(data):
if verbose: if verbose:
print 'findfactor' print 'findfactor'
if audioop.findfactor(data[1], data[1]) <> 1.0: if audioop.findfactor(data[1], data[1]) <> 1.0:
return 0 return 0
return 1 return 1
def testfindfit(data): def testfindfit(data):
if verbose: if verbose:
print 'findfit' print 'findfit'
if audioop.findfit(data[1], data[1]) <> (0, 1.0): if audioop.findfit(data[1], data[1]) <> (0, 1.0):
return 0 return 0
return 1 return 1
def testfindmax(data): def testfindmax(data):
if verbose: if verbose:
print 'findmax' print 'findmax'
if audioop.findmax(data[1], 1) <> 2: if audioop.findmax(data[1], 1) <> 2:
return 0 return 0
return 1 return 1
def testgetsample(data): def testgetsample(data):
if verbose: if verbose:
print 'getsample' print 'getsample'
for i in range(3): for i in range(3):
if audioop.getsample(data[0], 1, i) <> i or \ if audioop.getsample(data[0], 1, i) <> i or \
audioop.getsample(data[1], 2, i) <> i or \ audioop.getsample(data[1], 2, i) <> i or \
audioop.getsample(data[2], 4, i) <> i: audioop.getsample(data[2], 4, i) <> i:
return 0 return 0
return 1 return 1
def testone(name, data): def testone(name, data):
try: try:
func = eval('test'+name) func = eval('test'+name)
except NameError: except NameError:
print 'No test found for audioop.'+name+'()' print 'No test found for audioop.'+name+'()'
return return
try: try:
rv = func(data) rv = func(data)
except 'xx': except 'xx':
print 'Test FAILED for audioop.'+name+'() (with an exception)' print 'Test FAILED for audioop.'+name+'() (with an exception)'
return return
if not rv: if not rv:
print 'Test FAILED for audioop.'+name+'()' print 'Test FAILED for audioop.'+name+'()'
def testall(): def testall():
data = [gendata1(), gendata2(), gendata4()] data = [gendata1(), gendata2(), gendata4()]
...@@ -257,8 +257,8 @@ def testall(): ...@@ -257,8 +257,8 @@ def testall():
# We know there is a routine 'add' # We know there is a routine 'add'
routines = [] routines = []
for n in names: for n in names:
if type(eval('audioop.'+n)) == type(audioop.add): if type(eval('audioop.'+n)) == type(audioop.add):
routines.append(n) routines.append(n)
for n in routines: for n in routines:
testone(n, data) testone(n, data)
testall() testall()
...@@ -11,11 +11,11 @@ from test_support import verbose ...@@ -11,11 +11,11 @@ from test_support import verbose
def test(): def test():
try: try:
fname1 = tempfile.mktemp() fname1 = tempfile.mktemp()
fname2 = tempfile.mktemp() fname2 = tempfile.mktemp()
f = open(fname1, 'w') f = open(fname1, 'w')
except: except:
raise ImportError, "Cannot test binascii without a temp file" raise ImportError, "Cannot test binascii without a temp file"
start = 'Jack is my hero' start = 'Jack is my hero'
f.write(start) f.write(start)
...@@ -23,24 +23,24 @@ def test(): ...@@ -23,24 +23,24 @@ def test():
binhex.binhex(fname1, fname2) binhex.binhex(fname1, fname2)
if verbose: if verbose:
print 'binhex' print 'binhex'
binhex.hexbin(fname2, fname1) binhex.hexbin(fname2, fname1)
if verbose: if verbose:
print 'hexbin' print 'hexbin'
f = open(fname1, 'r') f = open(fname1, 'r')
finish = f.readline() finish = f.readline()
if start <> finish: if start <> finish:
print 'Error: binhex <> hexbin' print 'Error: binhex <> hexbin'
elif verbose: elif verbose:
print 'binhex == hexbin' print 'binhex == hexbin'
try: try:
import os import os
os.unlink(fname1) os.unlink(fname1)
os.unlink(fname2) os.unlink(fname2)
except: except:
pass pass
test() test()
...@@ -9,12 +9,12 @@ from test_support import verbose ...@@ -9,12 +9,12 @@ from test_support import verbose
def test(openmethod, what): def test(openmethod, what):
if verbose: if verbose:
print '\nTesting: ', what print '\nTesting: ', what
fname = tempfile.mktemp() fname = tempfile.mktemp()
f = openmethod(fname, 'c') f = openmethod(fname, 'c')
if verbose: if verbose:
print 'creation...' print 'creation...'
f['0'] = '' f['0'] = ''
f['a'] = 'Guido' f['a'] = 'Guido'
f['b'] = 'van' f['b'] = 'van'
...@@ -22,47 +22,47 @@ def test(openmethod, what): ...@@ -22,47 +22,47 @@ def test(openmethod, what):
f['d'] = 'invented' f['d'] = 'invented'
f['f'] = 'Python' f['f'] = 'Python'
if verbose: if verbose:
print '%s %s %s' % (f['a'], f['b'], f['c']) print '%s %s %s' % (f['a'], f['b'], f['c'])
if what == 'BTree' : if what == 'BTree' :
if verbose: if verbose:
print 'key ordering...' print 'key ordering...'
f.set_location(f.first()[0]) f.set_location(f.first()[0])
while 1: while 1:
try: try:
rec = f.next() rec = f.next()
except KeyError: except KeyError:
if rec <> f.last(): if rec <> f.last():
print 'Error, last <> last!' print 'Error, last <> last!'
f.previous() f.previous()
break break
if verbose: if verbose:
print rec print rec
if not f.has_key('a'): if not f.has_key('a'):
print 'Error, missing key!' print 'Error, missing key!'
f.sync() f.sync()
f.close() f.close()
if verbose: if verbose:
print 'modification...' print 'modification...'
f = openmethod(fname, 'w') f = openmethod(fname, 'w')
f['d'] = 'discovered' f['d'] = 'discovered'
if verbose: if verbose:
print 'access...' print 'access...'
for key in f.keys(): for key in f.keys():
word = f[key] word = f[key]
if verbose: if verbose:
print word print word
f.close() f.close()
types = [(bsddb.btopen, 'BTree'), types = [(bsddb.btopen, 'BTree'),
(bsddb.hashopen, 'Hash Table'), (bsddb.hashopen, 'Hash Table'),
# (bsddb.rnopen,'Record Numbers'), 'put' for RECNO for bsddb 1.85 # (bsddb.rnopen,'Record Numbers'), 'put' for RECNO for bsddb 1.85
# appears broken... at least on # appears broken... at least on
# Solaris Intel - rmasse 1/97 # Solaris Intel - rmasse 1/97
] ]
for type in types: for type in types:
test(type[0], type[1]) test(type[0], type[1])
......
...@@ -6,27 +6,27 @@ import cmath ...@@ -6,27 +6,27 @@ import cmath
from test_support import verbose from test_support import verbose
testdict = {'acos' : 1.0, testdict = {'acos' : 1.0,
'acosh' : 1.0, 'acosh' : 1.0,
'asin' : 1.0, 'asin' : 1.0,
'asinh' : 1.0, 'asinh' : 1.0,
'atan' : 0.2, 'atan' : 0.2,
'atanh' : 0.2, 'atanh' : 0.2,
'cos' : 1.0, 'cos' : 1.0,
'cosh' : 1.0, 'cosh' : 1.0,
'exp' : 1.0, 'exp' : 1.0,
'log' : 1.0, 'log' : 1.0,
'log10' : 1.0, 'log10' : 1.0,
'sin' : 1.0, 'sin' : 1.0,
'sinh' : 1.0, 'sinh' : 1.0,
'sqrt' : 1.0, 'sqrt' : 1.0,
'tan' : 1.0, 'tan' : 1.0,
'tanh' : 1.0} 'tanh' : 1.0}
for func in testdict.keys(): for func in testdict.keys():
f = getattr(cmath, func) f = getattr(cmath, func)
r = f(testdict[func]) r = f(testdict[func])
if verbose: if verbose:
print 'Calling %s(%f) = %f' % (func, testdict[func], abs(r)) print 'Calling %s(%f) = %f' % (func, testdict[func], abs(r))
p = cmath.pi p = cmath.pi
e = cmath.e e = cmath.e
......
...@@ -7,31 +7,31 @@ import errno ...@@ -7,31 +7,31 @@ import errno
from test_support import verbose from test_support import verbose
errors = ['E2BIG', 'EACCES', 'EADDRINUSE', 'EADDRNOTAVAIL', 'EADV', errors = ['E2BIG', 'EACCES', 'EADDRINUSE', 'EADDRNOTAVAIL', 'EADV',
'EAFNOSUPPORT', 'EAGAIN', 'EALREADY', 'EBADE', 'EBADF', 'EAFNOSUPPORT', 'EAGAIN', 'EALREADY', 'EBADE', 'EBADF',
'EBADFD', 'EBADMSG', 'EBADR', 'EBADRQC', 'EBADSLT', 'EBADFD', 'EBADMSG', 'EBADR', 'EBADRQC', 'EBADSLT',
'EBFONT', 'EBUSY', 'ECHILD', 'ECHRNG', 'ECOMM', 'EBFONT', 'EBUSY', 'ECHILD', 'ECHRNG', 'ECOMM',
'ECONNABORTED', 'ECONNREFUSED', 'ECONNRESET', 'ECONNABORTED', 'ECONNREFUSED', 'ECONNRESET',
'EDEADLK', 'EDEADLOCK', 'EDESTADDRREQ', 'EDOM', 'EDEADLK', 'EDEADLOCK', 'EDESTADDRREQ', 'EDOM',
'EDQUOT', 'EEXIST', 'EFAULT', 'EFBIG', 'EHOSTDOWN', 'EDQUOT', 'EEXIST', 'EFAULT', 'EFBIG', 'EHOSTDOWN',
'EHOSTUNREACH', 'EIDRM', 'EILSEQ', 'EINPROGRESS', 'EHOSTUNREACH', 'EIDRM', 'EILSEQ', 'EINPROGRESS',
'EINTR', 'EINVAL', 'EIO', 'EISCONN', 'EISDIR', 'EINTR', 'EINVAL', 'EIO', 'EISCONN', 'EISDIR',
'EL2HLT', 'EL2NSYNC', 'EL3HLT', 'EL3RST', 'ELIBACC', 'EL2HLT', 'EL2NSYNC', 'EL3HLT', 'EL3RST', 'ELIBACC',
'ELIBBAD', 'ELIBEXEC', 'ELIBMAX', 'ELIBSCN', 'ELNRNG', 'ELIBBAD', 'ELIBEXEC', 'ELIBMAX', 'ELIBSCN', 'ELNRNG',
'ELOOP', 'EMFILE', 'EMLINK', 'EMSGSIZE', 'EMULTIHOP', 'ELOOP', 'EMFILE', 'EMLINK', 'EMSGSIZE', 'EMULTIHOP',
'ENAMETOOLONG', 'ENETDOWN', 'ENETRESET', 'ENETUNREACH', 'ENAMETOOLONG', 'ENETDOWN', 'ENETRESET', 'ENETUNREACH',
'ENFILE', 'ENOANO', 'ENOBUFS', 'ENOCSI', 'ENODATA', 'ENFILE', 'ENOANO', 'ENOBUFS', 'ENOCSI', 'ENODATA',
'ENODEV', 'ENOENT', 'ENOEXEC', 'ENOLCK', 'ENOLINK', 'ENODEV', 'ENOENT', 'ENOEXEC', 'ENOLCK', 'ENOLINK',
'ENOMEM', 'ENOMSG', 'ENONET', 'ENOPKG', 'ENOPROTOOPT', 'ENOMEM', 'ENOMSG', 'ENONET', 'ENOPKG', 'ENOPROTOOPT',
'ENOSPC', 'ENOSR', 'ENOSTR', 'ENOSYS', 'ENOTBLK', 'ENOSPC', 'ENOSR', 'ENOSTR', 'ENOSYS', 'ENOTBLK',
'ENOTCONN', 'ENOTDIR', 'ENOTEMPTY', 'ENOTOBACCO', 'ENOTSOCK', 'ENOTCONN', 'ENOTDIR', 'ENOTEMPTY', 'ENOTOBACCO', 'ENOTSOCK',
'ENOTTY', 'ENOTUNIQ', 'ENXIO', 'EOPNOTSUPP', 'ENOTTY', 'ENOTUNIQ', 'ENXIO', 'EOPNOTSUPP',
'EOVERFLOW', 'EPERM', 'EPFNOSUPPORT', 'EPIPE', 'EOVERFLOW', 'EPERM', 'EPFNOSUPPORT', 'EPIPE',
'EPROTO', 'EPROTONOSUPPORT', 'EPROTOTYPE', 'EPROTO', 'EPROTONOSUPPORT', 'EPROTOTYPE',
'ERANGE', 'EREMCHG', 'EREMOTE', 'ERESTART', 'ERANGE', 'EREMCHG', 'EREMOTE', 'ERESTART',
'EROFS', 'ESHUTDOWN', 'ESOCKTNOSUPPORT', 'ESPIPE', 'EROFS', 'ESHUTDOWN', 'ESOCKTNOSUPPORT', 'ESPIPE',
'ESRCH', 'ESRMNT', 'ESTALE', 'ESTRPIPE', 'ETIME', 'ESRCH', 'ESRMNT', 'ESTALE', 'ESTRPIPE', 'ETIME',
'ETIMEDOUT', 'ETOOMANYREFS', 'ETXTBSY', 'EUNATCH', 'ETIMEDOUT', 'ETOOMANYREFS', 'ETXTBSY', 'EUNATCH',
'EUSERS', 'EWOULDBLOCK', 'EXDEV', 'EXFULL'] 'EUSERS', 'EWOULDBLOCK', 'EXDEV', 'EXFULL']
# #
# This is is a wee bit bogus since the module only conditionally adds # This is is a wee bit bogus since the module only conditionally adds
...@@ -40,10 +40,10 @@ errors = ['E2BIG', 'EACCES', 'EADDRINUSE', 'EADDRNOTAVAIL', 'EADV', ...@@ -40,10 +40,10 @@ errors = ['E2BIG', 'EACCES', 'EADDRINUSE', 'EADDRNOTAVAIL', 'EADV',
# #
for error in errors: for error in errors:
try: try:
a = getattr(errno, error) a = getattr(errno, error)
except AttributeError: except AttributeError:
if verbose: if verbose:
print '%s: not found' % error print '%s: not found' % error
else: else:
if verbose: if verbose:
print '%s: %d' % (error, a) print '%s: %d' % (error, a)
...@@ -8,9 +8,9 @@ print '5. Built-in exceptions' ...@@ -8,9 +8,9 @@ print '5. Built-in exceptions'
def r(thing): def r(thing):
if type(thing) == ClassType: if type(thing) == ClassType:
print thing.__name__ print thing.__name__
else: else:
print thing print thing
r(AttributeError) r(AttributeError)
import sys import sys
...@@ -24,14 +24,14 @@ fp.close() ...@@ -24,14 +24,14 @@ fp.close()
fp = open(TESTFN, 'r') fp = open(TESTFN, 'r')
savestdin = sys.stdin savestdin = sys.stdin
try: try:
try: try:
sys.stdin = fp sys.stdin = fp
x = raw_input() x = raw_input()
except EOFError: except EOFError:
pass pass
finally: finally:
sys.stdin = savestdin sys.stdin = savestdin
fp.close() fp.close()
r(IOError) r(IOError)
try: open('this file does not exist', 'r') try: open('this file does not exist', 'r')
...@@ -64,7 +64,7 @@ except NameError: pass ...@@ -64,7 +64,7 @@ except NameError: pass
r(OverflowError) r(OverflowError)
x = 1 x = 1
try: try:
while 1: x = x+x while 1: x = x+x
except OverflowError: pass except OverflowError: pass
r(RuntimeError) r(RuntimeError)
......
...@@ -15,14 +15,14 @@ def main(use_rgbimg=1): ...@@ -15,14 +15,14 @@ def main(use_rgbimg=1):
uu.decode(get_qualified_path('testrgb.uue'), 'test.rgb') uu.decode(get_qualified_path('testrgb.uue'), 'test.rgb')
if use_rgbimg: if use_rgbimg:
image, width, height = getrgbimage('test.rgb') image, width, height = getrgbimage('test.rgb')
else: else:
image, width, height = getimage('test.rgb') image, width, height = getimage('test.rgb')
# Return the selected part of image, which should by width by height # Return the selected part of image, which should by width by height
# in size and consist of pixels of psize bytes. # in size and consist of pixels of psize bytes.
if verbose: if verbose:
print 'crop' print 'crop'
newimage = imageop.crop (image, 4, width, height, 0, 0, 1, 1) newimage = imageop.crop (image, 4, width, height, 0, 0, 1, 1)
# Return image scaled to size newwidth by newheight. No interpolation # Return image scaled to size newwidth by newheight. No interpolation
...@@ -30,7 +30,7 @@ def main(use_rgbimg=1): ...@@ -30,7 +30,7 @@ def main(use_rgbimg=1):
# Therefore, computer-generated images or dithered images will # Therefore, computer-generated images or dithered images will
# not look nice after scaling. # not look nice after scaling.
if verbose: if verbose:
print 'scale' print 'scale'
scaleimage = imageop.scale(image, 4, width, height, 1, 1) scaleimage = imageop.scale(image, 4, width, height, 1, 1)
# Run a vertical low-pass filter over an image. It does so by computing # Run a vertical low-pass filter over an image. It does so by computing
...@@ -38,34 +38,34 @@ def main(use_rgbimg=1): ...@@ -38,34 +38,34 @@ def main(use_rgbimg=1):
# pixels. The main use of this routine is to forestall excessive flicker # pixels. The main use of this routine is to forestall excessive flicker
# if the image two vertically-aligned source pixels, hence the name. # if the image two vertically-aligned source pixels, hence the name.
if verbose: if verbose:
print 'tovideo' print 'tovideo'
videoimage = imageop.tovideo (image, 4, width, height) videoimage = imageop.tovideo (image, 4, width, height)
# Convert an rgb image to an 8 bit rgb # Convert an rgb image to an 8 bit rgb
if verbose: if verbose:
print 'rgb2rgb8' print 'rgb2rgb8'
greyimage = imageop.rgb2rgb8(image, width, height) greyimage = imageop.rgb2rgb8(image, width, height)
# Convert an 8 bit rgb image to a 24 bit rgb image # Convert an 8 bit rgb image to a 24 bit rgb image
if verbose: if verbose:
print 'rgb82rgb' print 'rgb82rgb'
image = imageop.rgb82rgb(greyimage, width, height) image = imageop.rgb82rgb(greyimage, width, height)
# Convert an rgb image to an 8 bit greyscale image # Convert an rgb image to an 8 bit greyscale image
if verbose: if verbose:
print 'rgb2grey' print 'rgb2grey'
greyimage = imageop.rgb2grey(image, width, height) greyimage = imageop.rgb2grey(image, width, height)
# Convert an 8 bit greyscale image to a 24 bit rgb image # Convert an 8 bit greyscale image to a 24 bit rgb image
if verbose: if verbose:
print 'grey2rgb' print 'grey2rgb'
image = imageop.grey2rgb(greyimage, width, height) image = imageop.grey2rgb(greyimage, width, height)
# Convert a 8-bit deep greyscale image to a 1-bit deep image by # Convert a 8-bit deep greyscale image to a 1-bit deep image by
# tresholding all the pixels. The resulting image is tightly packed # tresholding all the pixels. The resulting image is tightly packed
# and is probably only useful as an argument to mono2grey. # and is probably only useful as an argument to mono2grey.
if verbose: if verbose:
print 'grey2mono' print 'grey2mono'
monoimage = imageop.grey2mono (greyimage, width, height, 0) monoimage = imageop.grey2mono (greyimage, width, height, 0)
# monoimage, width, height = getimage('monotest.rgb') # monoimage, width, height = getimage('monotest.rgb')
...@@ -75,42 +75,42 @@ def main(use_rgbimg=1): ...@@ -75,42 +75,42 @@ def main(use_rgbimg=1):
# monochrome black-and-white image to greyscale pass the values 0 and # monochrome black-and-white image to greyscale pass the values 0 and
# 255 respectively. # 255 respectively.
if verbose: if verbose:
print 'mono2grey' print 'mono2grey'
greyimage = imageop.mono2grey (monoimage, width, height, 0, 255) greyimage = imageop.mono2grey (monoimage, width, height, 0, 255)
# Convert an 8-bit greyscale image to a 1-bit monochrome image using a # Convert an 8-bit greyscale image to a 1-bit monochrome image using a
# (simple-minded) dithering algorithm. # (simple-minded) dithering algorithm.
if verbose: if verbose:
print 'dither2mono' print 'dither2mono'
monoimage = imageop.dither2mono (greyimage, width, height) monoimage = imageop.dither2mono (greyimage, width, height)
# Convert an 8-bit greyscale image to a 4-bit greyscale image without # Convert an 8-bit greyscale image to a 4-bit greyscale image without
# dithering. # dithering.
if verbose: if verbose:
print 'grey2grey4' print 'grey2grey4'
grey4image = imageop.grey2grey4 (greyimage, width, height) grey4image = imageop.grey2grey4 (greyimage, width, height)
# Convert an 8-bit greyscale image to a 2-bit greyscale image without # Convert an 8-bit greyscale image to a 2-bit greyscale image without
# dithering. # dithering.
if verbose: if verbose:
print 'grey2grey2' print 'grey2grey2'
grey2image = imageop.grey2grey2 (greyimage, width, height) grey2image = imageop.grey2grey2 (greyimage, width, height)
# Convert an 8-bit greyscale image to a 2-bit greyscale image with # Convert an 8-bit greyscale image to a 2-bit greyscale image with
# dithering. As for dither2mono, the dithering algorithm is currently # dithering. As for dither2mono, the dithering algorithm is currently
# very simple. # very simple.
if verbose: if verbose:
print 'dither2grey2' print 'dither2grey2'
grey2image = imageop.dither2grey2 (greyimage, width, height) grey2image = imageop.dither2grey2 (greyimage, width, height)
# Convert a 4-bit greyscale image to an 8-bit greyscale image. # Convert a 4-bit greyscale image to an 8-bit greyscale image.
if verbose: if verbose:
print 'grey42grey' print 'grey42grey'
greyimage = imageop.grey42grey (grey4image, width, height) greyimage = imageop.grey42grey (grey4image, width, height)
# Convert a 2-bit greyscale image to an 8-bit greyscale image. # Convert a 2-bit greyscale image to an 8-bit greyscale image.
if verbose: if verbose:
print 'grey22grey' print 'grey22grey'
image = imageop.grey22grey (grey2image, width, height) image = imageop.grey22grey (grey2image, width, height)
# Cleanup # Cleanup
...@@ -123,12 +123,12 @@ def getrgbimage(name): ...@@ -123,12 +123,12 @@ def getrgbimage(name):
import rgbimg import rgbimg
try: try:
sizes = rgbimg.sizeofimage(name) sizes = rgbimg.sizeofimage(name)
except rgbimg.error: except rgbimg.error:
name = get_qualified_path(name) name = get_qualified_path(name)
sizes = rgbimg.sizeofimage(name) sizes = rgbimg.sizeofimage(name)
if verbose: if verbose:
print 'rgbimg opening test image: %s, sizes: %s' % (name, str(sizes)) print 'rgbimg opening test image: %s, sizes: %s' % (name, str(sizes))
image = rgbimg.longimagedata(name) image = rgbimg.longimagedata(name)
return (image, sizes[0], sizes[1]) return (image, sizes[0], sizes[1])
...@@ -141,12 +141,12 @@ def getimage(name): ...@@ -141,12 +141,12 @@ def getimage(name):
import imgfile import imgfile
try: try:
sizes = imgfile.getsizes(name) sizes = imgfile.getsizes(name)
except imgfile.error: except imgfile.error:
name = get_qualified_path(name) name = get_qualified_path(name)
sizes = imgfile.getsizes(name) sizes = imgfile.getsizes(name)
if verbose: if verbose:
print 'imgfile opening test image: %s, sizes: %s' % (name, str(sizes)) print 'imgfile opening test image: %s, sizes: %s' % (name, str(sizes))
image = imgfile.read(name) image = imgfile.read(name)
return (image, sizes[0], sizes[1]) return (image, sizes[0], sizes[1])
...@@ -157,13 +157,13 @@ def get_qualified_path(name): ...@@ -157,13 +157,13 @@ def get_qualified_path(name):
import os import os
path = sys.path path = sys.path
try: try:
path = [os.path.dirname(__file__)] + path path = [os.path.dirname(__file__)] + path
except NameError: except NameError:
pass pass
for dir in path: for dir in path:
fullname = os.path.join(dir, name) fullname = os.path.join(dir, name)
if os.path.exists(fullname): if os.path.exists(fullname):
return fullname return fullname
return name return name
# rgbimg (unlike imgfile) is portable to platforms other than SGI. # rgbimg (unlike imgfile) is portable to platforms other than SGI.
......
...@@ -24,12 +24,12 @@ def main(): ...@@ -24,12 +24,12 @@ def main():
unlink('greytest.rgb') unlink('greytest.rgb')
def findfile(file): def findfile(file):
if os.path.isabs(file): return file if os.path.isabs(file): return file
import sys import sys
for dn in sys.path: for dn in sys.path:
fn = os.path.join(dn, file) fn = os.path.join(dn, file)
if os.path.exists(fn): return fn if os.path.exists(fn): return fn
return file return file
def testimage(name): def testimage(name):
"""Run through the imgfile's battery of possible methods """Run through the imgfile's battery of possible methods
...@@ -44,23 +44,23 @@ def testimage(name): ...@@ -44,23 +44,23 @@ def testimage(name):
# try opening the name directly # try opening the name directly
try: try:
# This function returns a tuple (x, y, z) where x and y are the size # This function returns a tuple (x, y, z) where x and y are the size
# of the image in pixels and z is the number of bytes per pixel. Only # of the image in pixels and z is the number of bytes per pixel. Only
# 3 byte RGB pixels and 1 byte greyscale pixels are supported. # 3 byte RGB pixels and 1 byte greyscale pixels are supported.
sizes = imgfile.getsizes(name) sizes = imgfile.getsizes(name)
except imgfile.error: except imgfile.error:
# get a more qualified path component of the script... # get a more qualified path component of the script...
if __name__ == '__main__': if __name__ == '__main__':
ourname = sys.argv[0] ourname = sys.argv[0]
else: # ...or the full path of the module else: # ...or the full path of the module
ourname = sys.modules[__name__].__file__ ourname = sys.modules[__name__].__file__
parts = string.splitfields(ourname, os.sep) parts = string.splitfields(ourname, os.sep)
parts[-1] = name parts[-1] = name
name = string.joinfields(parts, os.sep) name = string.joinfields(parts, os.sep)
sizes = imgfile.getsizes(name) sizes = imgfile.getsizes(name)
if verbose: if verbose:
print 'Opening test image: %s, sizes: %s' % (name, str(sizes)) print 'Opening test image: %s, sizes: %s' % (name, str(sizes))
# This function reads and decodes the image on the specified file, # This function reads and decodes the image on the specified file,
# and returns it as a python string. The string has either 1 byte # and returns it as a python string. The string has either 1 byte
# greyscale pixels or 4 byte RGBA pixels. The bottom left pixel # greyscale pixels or 4 byte RGBA pixels. The bottom left pixel
...@@ -74,12 +74,12 @@ def testimage(name): ...@@ -74,12 +74,12 @@ def testimage(name):
# are stored as 4 byte values of which only the lower three # are stored as 4 byte values of which only the lower three
# bytes are used). These are the formats returned by gl.lrectread. # bytes are used). These are the formats returned by gl.lrectread.
if verbose: if verbose:
print 'Writing output file' print 'Writing output file'
imgfile.write (outputfile, image, sizes[0], sizes[1], sizes[2]) imgfile.write (outputfile, image, sizes[0], sizes[1], sizes[2])
if verbose: if verbose:
print 'Opening scaled test image: %s, sizes: %s' % (name, str(sizes)) print 'Opening scaled test image: %s, sizes: %s' % (name, str(sizes))
# This function is identical to read but it returns an image that # This function is identical to read but it returns an image that
# is scaled to the given x and y sizes. If the filter and blur # is scaled to the given x and y sizes. If the filter and blur
# parameters are omitted scaling is done by simply dropping # parameters are omitted scaling is done by simply dropping
...@@ -93,7 +93,7 @@ def testimage(name): ...@@ -93,7 +93,7 @@ def testimage(name):
# makes no attempt to keep the aspect ratio correct, so that # makes no attempt to keep the aspect ratio correct, so that
# is the users' responsibility. # is the users' responsibility.
if verbose: if verbose:
print 'Filtering with "impulse"' print 'Filtering with "impulse"'
simage = imgfile.readscaled (name, sizes[0]/2, sizes[1]/2, 'impulse', 2.0) simage = imgfile.readscaled (name, sizes[0]/2, sizes[1]/2, 'impulse', 2.0)
# This function sets a global flag which defines whether the # This function sets a global flag which defines whether the
...@@ -101,14 +101,14 @@ def testimage(name): ...@@ -101,14 +101,14 @@ def testimage(name):
# top (flag is zero, compatible with SGI GL) or from top to # top (flag is zero, compatible with SGI GL) or from top to
# bottom(flag is one, compatible with X). The default is zero. # bottom(flag is one, compatible with X). The default is zero.
if verbose: if verbose:
print 'Switching to X compatibility' print 'Switching to X compatibility'
imgfile.ttob (1) imgfile.ttob (1)
if verbose: if verbose:
print 'Filtering with "triangle"' print 'Filtering with "triangle"'
simage = imgfile.readscaled (name, sizes[0]/2, sizes[1]/2, 'triangle', 3.0) simage = imgfile.readscaled (name, sizes[0]/2, sizes[1]/2, 'triangle', 3.0)
if verbose: if verbose:
print 'Switching back to SGI compatibility' print 'Switching back to SGI compatibility'
imgfile.ttob (0) imgfile.ttob (0)
if verbose: print 'Filtering with "quadratic"' if verbose: print 'Filtering with "quadratic"'
...@@ -117,7 +117,7 @@ def testimage(name): ...@@ -117,7 +117,7 @@ def testimage(name):
simage = imgfile.readscaled (name, sizes[0]/2, sizes[1]/2, 'gaussian', 1.0) simage = imgfile.readscaled (name, sizes[0]/2, sizes[1]/2, 'gaussian', 1.0)
if verbose: if verbose:
print 'Writing output file' print 'Writing output file'
imgfile.write (outputfile, simage, sizes[0]/2, sizes[1]/2, sizes[2]) imgfile.write (outputfile, simage, sizes[0]/2, sizes[1]/2, sizes[2])
os.unlink(outputfile) os.unlink(outputfile)
......
...@@ -9,18 +9,18 @@ print 'XXX Not yet fully implemented' ...@@ -9,18 +9,18 @@ print 'XXX Not yet fully implemented'
print '2.1 try inside for loop' print '2.1 try inside for loop'
n = 0 n = 0
for i in range(10): for i in range(10):
n = n+i n = n+i
try: 1/0 try: 1/0
except NameError: pass except NameError: pass
except ZeroDivisionError: pass except ZeroDivisionError: pass
except TypeError: pass except TypeError: pass
try: pass try: pass
except: pass except: pass
try: pass try: pass
finally: pass finally: pass
n = n+i n = n+i
if n <> 90: if n <> 90:
raise TestFailed, 'try inside for' raise TestFailed, 'try inside for'
print '2.2 raise class exceptions' print '2.2 raise class exceptions'
...@@ -30,7 +30,7 @@ class BClass(AClass): pass ...@@ -30,7 +30,7 @@ class BClass(AClass): pass
class CClass: pass class CClass: pass
class DClass(AClass): class DClass(AClass):
def __init__(self, ignore): def __init__(self, ignore):
pass pass
try: raise AClass() try: raise AClass()
except: pass except: pass
...@@ -50,12 +50,12 @@ b = BClass() ...@@ -50,12 +50,12 @@ b = BClass()
try: raise AClass, b try: raise AClass, b
except BClass, v: except BClass, v:
if v != b: raise TestFailed if v != b: raise TestFailed
else: raise TestFailed else: raise TestFailed
try: raise b try: raise b
except AClass, v: except AClass, v:
if v != b: raise TestFailed if v != b: raise TestFailed
# not enough arguments # not enough arguments
try: raise BClass, a try: raise BClass, a
...@@ -64,7 +64,7 @@ except TypeError: pass ...@@ -64,7 +64,7 @@ except TypeError: pass
try: raise DClass, a try: raise DClass, a
except DClass, v: except DClass, v:
if not isinstance(v, DClass): if not isinstance(v, DClass):
raise TestFailed raise TestFailed
print '2.3 comparing function objects' print '2.3 comparing function objects'
......
...@@ -67,44 +67,44 @@ if verbose: print 'Running regex_tests test suite' ...@@ -67,44 +67,44 @@ if verbose: print 'Running regex_tests test suite'
for t in tests: for t in tests:
pattern=s=outcome=repl=expected=None pattern=s=outcome=repl=expected=None
if len(t)==5: if len(t)==5:
pattern, s, outcome, repl, expected = t pattern, s, outcome, repl, expected = t
elif len(t)==3: elif len(t)==3:
pattern, s, outcome = t pattern, s, outcome = t
else: else:
raise ValueError, ('Test tuples should have 3 or 5 fields',t) raise ValueError, ('Test tuples should have 3 or 5 fields',t)
try: try:
obj=regex.compile(pattern) obj=regex.compile(pattern)
except regex.error: except regex.error:
if outcome==SYNTAX_ERROR: pass # Expected a syntax error if outcome==SYNTAX_ERROR: pass # Expected a syntax error
else: else:
# Regex syntax errors aren't yet reported, so for # Regex syntax errors aren't yet reported, so for
# the official test suite they'll be quietly ignored. # the official test suite they'll be quietly ignored.
pass pass
#print '=== Syntax error:', t #print '=== Syntax error:', t
else: else:
try: try:
result=obj.search(s) result=obj.search(s)
except regex.error, msg: except regex.error, msg:
print '=== Unexpected exception', t, repr(msg) print '=== Unexpected exception', t, repr(msg)
if outcome==SYNTAX_ERROR: if outcome==SYNTAX_ERROR:
# This should have been a syntax error; forget it. # This should have been a syntax error; forget it.
pass pass
elif outcome==FAIL: elif outcome==FAIL:
if result==-1: pass # No match, as expected if result==-1: pass # No match, as expected
else: print '=== Succeeded incorrectly', t else: print '=== Succeeded incorrectly', t
elif outcome==SUCCEED: elif outcome==SUCCEED:
if result!=-1: if result!=-1:
# Matched, as expected, so now we compute the # Matched, as expected, so now we compute the
# result string and compare it to our expected result. # result string and compare it to our expected result.
start, end = obj.regs[0] start, end = obj.regs[0]
found=s[start:end] found=s[start:end]
groups=obj.group(1,2,3,4,5,6,7,8,9,10) groups=obj.group(1,2,3,4,5,6,7,8,9,10)
vardict=vars() vardict=vars()
for i in range(len(groups)): for i in range(len(groups)):
vardict['g'+str(i+1)]=str(groups[i]) vardict['g'+str(i+1)]=str(groups[i])
repl=eval(repl) repl=eval(repl)
if repl!=expected: if repl!=expected:
print '=== grouping error', t, repr(repl)+' should be '+repr(expected) print '=== grouping error', t, repr(repl)+' should be '+repr(expected)
else: else:
print '=== Failed incorrectly', t print '=== Failed incorrectly', t
...@@ -9,32 +9,32 @@ error = 'test_rgbimg.error' ...@@ -9,32 +9,32 @@ error = 'test_rgbimg.error'
print 'RGBimg test suite:' print 'RGBimg test suite:'
def findfile(file): def findfile(file):
if os.path.isabs(file): return file if os.path.isabs(file): return file
import sys import sys
path = sys.path path = sys.path
try: try:
path = [os.path.dirname(__file__)] + path path = [os.path.dirname(__file__)] + path
except NameError: except NameError:
pass pass
for dn in path: for dn in path:
fn = os.path.join(dn, file) fn = os.path.join(dn, file)
if os.path.exists(fn): return fn if os.path.exists(fn): return fn
return file return file
def testimg(rgb_file, raw_file): def testimg(rgb_file, raw_file):
rgb_file = findfile(rgb_file) rgb_file = findfile(rgb_file)
raw_file = findfile(raw_file) raw_file = findfile(raw_file)
width, height = rgbimg.sizeofimage(rgb_file) width, height = rgbimg.sizeofimage(rgb_file)
rgb = rgbimg.longimagedata(rgb_file) rgb = rgbimg.longimagedata(rgb_file)
if len(rgb) != width * height * 4: if len(rgb) != width * height * 4:
raise error, 'bad image length' raise error, 'bad image length'
raw = open(raw_file, 'rb').read() raw = open(raw_file, 'rb').read()
if rgb != raw: if rgb != raw:
raise error, \ raise error, \
'images don\'t match for '+rgb_file+' and '+raw_file 'images don\'t match for '+rgb_file+' and '+raw_file
for depth in [1, 3, 4]: for depth in [1, 3, 4]:
rgbimg.longstoimage(rgb, width, height, depth, '@.rgb') rgbimg.longstoimage(rgb, width, height, depth, '@.rgb')
os.unlink('@.rgb') os.unlink('@.rgb')
table = [ table = [
('testrgb.uue', 'test.rgb'), ('testrgb.uue', 'test.rgb'),
...@@ -45,7 +45,7 @@ for source, target in table: ...@@ -45,7 +45,7 @@ for source, target in table:
source = findfile(source) source = findfile(source)
target = findfile(target) target = findfile(target)
if verbose: if verbose:
print "uudecoding", source, "->", target, "..." print "uudecoding", source, "->", target, "..."
uu.decode(source, target) uu.decode(source, target)
if verbose: if verbose:
...@@ -53,23 +53,23 @@ if verbose: ...@@ -53,23 +53,23 @@ if verbose:
ttob = rgbimg.ttob(0) ttob = rgbimg.ttob(0)
if ttob != 0: if ttob != 0:
raise error, 'ttob should start out as zero' raise error, 'ttob should start out as zero'
testimg('test.rgb', 'test.rawimg') testimg('test.rgb', 'test.rawimg')
ttob = rgbimg.ttob(1) ttob = rgbimg.ttob(1)
if ttob != 0: if ttob != 0:
raise error, 'ttob should be zero' raise error, 'ttob should be zero'
testimg('test.rgb', 'test.rawimg.rev') testimg('test.rgb', 'test.rawimg.rev')
ttob = rgbimg.ttob(0) ttob = rgbimg.ttob(0)
if ttob != 1: if ttob != 1:
raise error, 'ttob should be one' raise error, 'ttob should be one'
ttob = rgbimg.ttob(0) ttob = rgbimg.ttob(0)
if ttob != 0: if ttob != 0:
raise error, 'ttob should be zero' raise error, 'ttob should be zero'
for source, target in table: for source, target in table:
unlink(findfile(target)) unlink(findfile(target))
...@@ -16,7 +16,7 @@ class Nope: ...@@ -16,7 +16,7 @@ class Nope:
class Almost: class Almost:
def fileno(self): def fileno(self):
return 'fileno' return 'fileno'
try: try:
rfd, wfd, xfd = select.select([Nope()], [], []) rfd, wfd, xfd = select.select([Nope()], [], [])
...@@ -34,31 +34,31 @@ else: ...@@ -34,31 +34,31 @@ else:
def test(): def test():
import sys import sys
if sys.platform[:3] in ('win', 'mac', 'os2'): if sys.platform[:3] in ('win', 'mac', 'os2'):
if verbose: if verbose:
print "Can't test select easily on", sys.platform print "Can't test select easily on", sys.platform
return return
cmd = 'for i in 0 1 2 3 4 5 6 7 8 9; do echo testing...; sleep 1; done' cmd = 'for i in 0 1 2 3 4 5 6 7 8 9; do echo testing...; sleep 1; done'
p = os.popen(cmd, 'r') p = os.popen(cmd, 'r')
for tout in (0, 1, 2, 4, 8, 16) + (None,)*10: for tout in (0, 1, 2, 4, 8, 16) + (None,)*10:
if verbose: if verbose:
print 'timeout =', tout print 'timeout =', tout
rfd, wfd, xfd = select.select([p], [], [], tout) rfd, wfd, xfd = select.select([p], [], [], tout)
## print rfd, wfd, xfd ## print rfd, wfd, xfd
if (rfd, wfd, xfd) == ([], [], []): if (rfd, wfd, xfd) == ([], [], []):
continue continue
if (rfd, wfd, xfd) == ([p], [], []): if (rfd, wfd, xfd) == ([p], [], []):
line = p.readline() line = p.readline()
if verbose: if verbose:
print `line` print `line`
if not line: if not line:
if verbose: if verbose:
print 'EOF' print 'EOF'
break break
continue continue
print 'Heh?' print 'Heh?'
p.close() p.close()
test() test()
# Not tested: # Not tested:
# socket.fromfd() # socket.fromfd()
# sktobj.getsockopt() # sktobj.getsockopt()
# sktobj.recvfrom() # sktobj.recvfrom()
# sktobj.sendto() # sktobj.sendto()
# sktobj.setblocking() # sktobj.setblocking()
# sktobj.setsockopt() # sktobj.setsockopt()
# sktobj.shutdown() # sktobj.shutdown()
from test_support import verbose, TestFailed from test_support import verbose, TestFailed
...@@ -16,9 +16,9 @@ import string ...@@ -16,9 +16,9 @@ import string
def missing_ok(str): def missing_ok(str):
try: try:
getattr(socket, str) getattr(socket, str)
except AttributeError: except AttributeError:
pass pass
try: raise socket.error try: raise socket.error
except socket.error: print "socket.error" except socket.error: print "socket.error"
...@@ -33,37 +33,37 @@ socket.SOCK_SEQPACKET ...@@ -33,37 +33,37 @@ socket.SOCK_SEQPACKET
for optional in ("AF_UNIX", for optional in ("AF_UNIX",
"SO_DEBUG", "SO_ACCEPTCONN", "SO_REUSEADDR", "SO_KEEPALIVE", "SO_DEBUG", "SO_ACCEPTCONN", "SO_REUSEADDR", "SO_KEEPALIVE",
"SO_DONTROUTE", "SO_BROADCAST", "SO_USELOOPBACK", "SO_LINGER", "SO_DONTROUTE", "SO_BROADCAST", "SO_USELOOPBACK", "SO_LINGER",
"SO_OOBINLINE", "SO_REUSEPORT", "SO_SNDBUF", "SO_RCVBUF", "SO_OOBINLINE", "SO_REUSEPORT", "SO_SNDBUF", "SO_RCVBUF",
"SO_SNDLOWAT", "SO_RCVLOWAT", "SO_SNDTIMEO", "SO_RCVTIMEO", "SO_SNDLOWAT", "SO_RCVLOWAT", "SO_SNDTIMEO", "SO_RCVTIMEO",
"SO_ERROR", "SO_TYPE", "SOMAXCONN", "SO_ERROR", "SO_TYPE", "SOMAXCONN",
"MSG_OOB", "MSG_PEEK", "MSG_DONTROUTE", "MSG_EOR", "MSG_OOB", "MSG_PEEK", "MSG_DONTROUTE", "MSG_EOR",
"MSG_TRUNC", "MSG_CTRUNC", "MSG_WAITALL", "MSG_BTAG", "MSG_TRUNC", "MSG_CTRUNC", "MSG_WAITALL", "MSG_BTAG",
"MSG_ETAG", "MSG_ETAG",
"SOL_SOCKET", "SOL_SOCKET",
"IPPROTO_IP", "IPPROTO_ICMP", "IPPROTO_IGMP", "IPPROTO_IP", "IPPROTO_ICMP", "IPPROTO_IGMP",
"IPPROTO_GGP", "IPPROTO_TCP", "IPPROTO_EGP", "IPPROTO_GGP", "IPPROTO_TCP", "IPPROTO_EGP",
"IPPROTO_PUP", "IPPROTO_UDP", "IPPROTO_IDP", "IPPROTO_PUP", "IPPROTO_UDP", "IPPROTO_IDP",
"IPPROTO_HELLO", "IPPROTO_ND", "IPPROTO_TP", "IPPROTO_HELLO", "IPPROTO_ND", "IPPROTO_TP",
"IPPROTO_XTP", "IPPROTO_EON", "IPPROTO_BIP", "IPPROTO_XTP", "IPPROTO_EON", "IPPROTO_BIP",
"IPPROTO_RAW", "IPPROTO_MAX", "IPPROTO_RAW", "IPPROTO_MAX",
"IPPORT_RESERVED", "IPPORT_USERRESERVED", "IPPORT_RESERVED", "IPPORT_USERRESERVED",
"INADDR_ANY", "INADDR_BROADCAST", "INADDR_LOOPBACK", "INADDR_ANY", "INADDR_BROADCAST", "INADDR_LOOPBACK",
"INADDR_UNSPEC_GROUP", "INADDR_ALLHOSTS_GROUP", "INADDR_UNSPEC_GROUP", "INADDR_ALLHOSTS_GROUP",
"INADDR_MAX_LOCAL_GROUP", "INADDR_NONE", "INADDR_MAX_LOCAL_GROUP", "INADDR_NONE",
"IP_OPTIONS", "IP_HDRINCL", "IP_TOS", "IP_TTL", "IP_OPTIONS", "IP_HDRINCL", "IP_TOS", "IP_TTL",
"IP_RECVOPTS", "IP_RECVRETOPTS", "IP_RECVDSTADDR", "IP_RECVOPTS", "IP_RECVRETOPTS", "IP_RECVDSTADDR",
"IP_RETOPTS", "IP_MULTICAST_IF", "IP_MULTICAST_TTL", "IP_RETOPTS", "IP_MULTICAST_IF", "IP_MULTICAST_TTL",
"IP_MULTICAST_LOOP", "IP_ADD_MEMBERSHIP", "IP_MULTICAST_LOOP", "IP_ADD_MEMBERSHIP",
"IP_DROP_MEMBERSHIP", "IP_DROP_MEMBERSHIP",
): ):
missing_ok(optional) missing_ok(optional)
socktype = socket.SocketType socktype = socket.SocketType
...@@ -80,7 +80,7 @@ if verbose: ...@@ -80,7 +80,7 @@ if verbose:
for name in all_host_names: for name in all_host_names:
if string.find(name, '.'): if string.find(name, '.'):
break break
else: else:
print 'FQDN not found' print 'FQDN not found'
...@@ -95,52 +95,52 @@ canfork = hasattr(os, 'fork') ...@@ -95,52 +95,52 @@ canfork = hasattr(os, 'fork')
try: try:
PORT = 50007 PORT = 50007
if not canfork or os.fork(): if not canfork or os.fork():
# parent is server # parent is server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(hostname, PORT) s.bind(hostname, PORT)
s.listen(1) s.listen(1)
if verbose: if verbose:
print 'parent accepting' print 'parent accepting'
if canfork: if canfork:
conn, addr = s.accept() conn, addr = s.accept()
if verbose: if verbose:
print 'connected by', addr print 'connected by', addr
# couple of interesting tests while we've got a live socket # couple of interesting tests while we've got a live socket
f = conn.fileno() f = conn.fileno()
if verbose: if verbose:
print 'fileno:', f print 'fileno:', f
p = conn.getpeername() p = conn.getpeername()
if verbose: if verbose:
print 'peer:', p print 'peer:', p
n = conn.getsockname() n = conn.getsockname()
if verbose: if verbose:
print 'sockname:', n print 'sockname:', n
f = conn.makefile() f = conn.makefile()
if verbose: if verbose:
print 'file obj:', f print 'file obj:', f
while 1: while 1:
data = conn.recv(1024) data = conn.recv(1024)
if not data: if not data:
break break
if verbose: if verbose:
print 'received:', data print 'received:', data
conn.send(data) conn.send(data)
conn.close() conn.close()
else: else:
try: try:
# child is client # child is client
time.sleep(5) time.sleep(5)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
if verbose: if verbose:
print 'child connecting' print 'child connecting'
s.connect(hostname, PORT) s.connect(hostname, PORT)
msg = 'socket test' msg = 'socket test'
s.send(msg) s.send(msg)
data = s.recv(1024) data = s.recv(1024)
if msg <> data: if msg <> data:
print 'parent/client mismatch' print 'parent/client mismatch'
s.close() s.close()
finally: finally:
os._exit(1) os._exit(1)
except socket.error, msg: except socket.error, msg:
raise TestFailed, msg raise TestFailed, msg
...@@ -3,19 +3,19 @@ import strop, sys ...@@ -3,19 +3,19 @@ import strop, sys
def test(name, input, output, *args): def test(name, input, output, *args):
if verbose: if verbose:
print 'string.%s%s =? %s... ' % (name, (input,) + args, output), print 'string.%s%s =? %s... ' % (name, (input,) + args, output),
f = getattr(strop, name) f = getattr(strop, name)
try: try:
value = apply(f, (input,) + args) value = apply(f, (input,) + args)
except: except:
value = sys.exc_type value = sys.exc_type
if value != output: if value != output:
if verbose: if verbose:
print 'no' print 'no'
print f, `input`, `output`, `value` print f, `input`, `output`, `value`
else: else:
if verbose: if verbose:
print 'yes' print 'yes'
test('atoi', " 1 ", 1) test('atoi', " 1 ", 1)
test('atoi', " 1x", ValueError) test('atoi', " 1x", ValueError)
......
...@@ -3,24 +3,29 @@ import sunaudiodev ...@@ -3,24 +3,29 @@ import sunaudiodev
import os import os
def findfile(file): def findfile(file):
if os.path.isabs(file): return file if os.path.isabs(file): return file
import sys import sys
for dn in sys.path: path = sys.path
fn = os.path.join(dn, file) try:
if os.path.exists(fn): return fn path = [os.path.dirname(__file__)] + path
return file except NameError:
pass
for dn in path:
fn = os.path.join(dn, file)
if os.path.exists(fn): return fn
return file
def play_sound_file(path): def play_sound_file(path):
fp = open(path, 'r') fp = open(path, 'r')
data = fp.read() data = fp.read()
fp.close() fp.close()
try: try:
a = sunaudiodev.open('w') a = sunaudiodev.open('w')
except sunaudiodev.error, msg: except sunaudiodev.error, msg:
raise TestFailed, msg raise TestFailed, msg
else: else:
a.write(data) a.write(data)
a.close() a.close()
def test(): def test():
play_sound_file(findfile('audiotest.au')) play_sound_file(findfile('audiotest.au'))
......
...@@ -14,13 +14,13 @@ if long(time.mktime(time.localtime(t))) <> long(t): ...@@ -14,13 +14,13 @@ if long(time.mktime(time.localtime(t))) <> long(t):
time.sleep(1.2) time.sleep(1.2)
tt = time.gmtime(t) tt = time.gmtime(t)
for directive in ('a', 'A', 'b', 'B', 'c', 'd', 'H', 'I', for directive in ('a', 'A', 'b', 'B', 'c', 'd', 'H', 'I',
'j', 'm', 'M', 'p', 'S', 'j', 'm', 'M', 'p', 'S',
'U', 'w', 'W', 'x', 'X', 'y', 'Y', 'Z', '%'): 'U', 'w', 'W', 'x', 'X', 'y', 'Y', 'Z', '%'):
format = ' %' + directive format = ' %' + directive
try: try:
time.strftime(format, tt) time.strftime(format, tt)
except ValueError: except ValueError:
print 'conversion specifier:', format, ' failed.' print 'conversion specifier:', format, ' failed.'
time.timezone time.timezone
time.tzname time.tzname
...@@ -33,7 +33,7 @@ except TypeError: ...@@ -33,7 +33,7 @@ except TypeError:
try: try:
time.mktime((999999, 999999, 999999, 999999, time.mktime((999999, 999999, 999999, 999999,
999999, 999999, 999999, 999999, 999999, 999999, 999999, 999999,
999999)) 999999))
except OverflowError: except OverflowError:
pass pass
...@@ -161,6 +161,11 @@ if a <> [-2,-1,0,1,2]: raise TestFailed, 'list sort' ...@@ -161,6 +161,11 @@ if a <> [-2,-1,0,1,2]: raise TestFailed, 'list sort'
def revcmp(a, b): return cmp(b, a) def revcmp(a, b): return cmp(b, a)
a.sort(revcmp) a.sort(revcmp)
if a <> [2,1,0,-1,-2]: raise TestFailed, 'list sort with cmp func' if a <> [2,1,0,-1,-2]: raise TestFailed, 'list sort with cmp func'
# The following dumps core in unpatched Python 1.5:
def myComparison(x,y):
return cmp(x%3, y%7)
z = range(12)
z.sort(myComparison)
print '6.6 Mappings == Dictionaries' print '6.6 Mappings == Dictionaries'
d = {} d = {}
......
...@@ -5,8 +5,8 @@ l = [4, 5, 6] ...@@ -5,8 +5,8 @@ l = [4, 5, 6]
class Seq: class Seq:
def __getitem__(self, i): def __getitem__(self, i):
if i >= 0 and i < 3: return i if i >= 0 and i < 3: return i
raise IndexError raise IndexError
a = -1 a = -1
b = -1 b = -1
...@@ -104,12 +104,12 @@ BozoError = 'BozoError' ...@@ -104,12 +104,12 @@ BozoError = 'BozoError'
class BadSeq: class BadSeq:
def __getitem__(self, i): def __getitem__(self, i):
if i >= 0 and i < 3: if i >= 0 and i < 3:
return i return i
elif i == 3: elif i == 3:
raise BozoError raise BozoError
else: else:
raise IndexError raise IndexError
# trigger code while not expecting an IndexError # trigger code while not expecting an IndexError
......
'''Test module to thest the xmllib module.
Sjoerd Mullender
'''
from test_support import verbose
testdoc = """\
<?xml version="1.0" encoding="UTF-8" standalone='yes' ?>
<!-- comments aren't allowed before the <?xml?> tag,
but they are allowed before the <!DOCTYPE> tag -->
<!DOCTYPE greeting [
<!ELEMENT greeting (#PCDATA)>
]>
<greeting>Hello, world!</greeting>
"""
import xmllib
if verbose:
parser = xmllib.TestXMLParser()
else:
parser = xmllib.XMLParser()
for c in testdoc:
parser.feed(c)
parser.close()
...@@ -87,6 +87,8 @@ def format_exception(etype, value, tb, limit = None): ...@@ -87,6 +87,8 @@ def format_exception(etype, value, tb, limit = None):
if tb: if tb:
list = ['Traceback (innermost last):\n'] list = ['Traceback (innermost last):\n']
list = list + format_tb(tb, limit) list = list + format_tb(tb, limit)
else:
list = []
list = list + format_exception_only(etype, value) list = list + format_exception_only(etype, value)
return list return list
...@@ -186,9 +188,13 @@ def extract_stack(f=None, limit = None): ...@@ -186,9 +188,13 @@ def extract_stack(f=None, limit = None):
# with -O on). # with -O on).
# Coded by Marc-Andre Lemburg from the example of PyCode_Addr2Line() # Coded by Marc-Andre Lemburg from the example of PyCode_Addr2Line()
# in compile.c. # in compile.c.
# Revised version by Jim Hugunin to work with JPython too.
def tb_lineno(tb): def tb_lineno(tb):
c = tb.tb_frame.f_code c = tb.tb_frame.f_code
if not hasattr(c, 'co_lnotab'):
return tb.tb_lineno
tab = c.co_lnotab tab = c.co_lnotab
line = c.co_firstlineno line = c.co_firstlineno
stopat = tb.tb_lasti stopat = tb.tb_lasti
......
...@@ -4,30 +4,30 @@ class UserDict: ...@@ -4,30 +4,30 @@ class UserDict:
def __init__(self): self.data = {} def __init__(self): self.data = {}
def __repr__(self): return repr(self.data) def __repr__(self): return repr(self.data)
def __cmp__(self, dict): def __cmp__(self, dict):
if type(dict) == type(self.data): if type(dict) == type(self.data):
return cmp(self.data, dict) return cmp(self.data, dict)
else: else:
return cmp(self.data, dict.data) return cmp(self.data, dict.data)
def __len__(self): return len(self.data) def __len__(self): return len(self.data)
def __getitem__(self, key): return self.data[key] def __getitem__(self, key): return self.data[key]
def __setitem__(self, key, item): self.data[key] = item def __setitem__(self, key, item): self.data[key] = item
def __delitem__(self, key): del self.data[key] def __delitem__(self, key): del self.data[key]
def clear(self): return self.data.clear() def clear(self): return self.data.clear()
def copy(self): def copy(self):
import copy import copy
return copy.copy(self) return copy.copy(self)
def keys(self): return self.data.keys() def keys(self): return self.data.keys()
def items(self): return self.data.items() def items(self): return self.data.items()
def values(self): return self.data.values() def values(self): return self.data.values()
def has_key(self, key): return self.data.has_key(key) def has_key(self, key): return self.data.has_key(key)
def update(self, other): def update(self, other):
if type(other) is type(self.data): if type(other) is type(self.data):
self.data.update(other) self.data.update(other)
else: else:
for k, v in other.items(): for k, v in other.items():
self.data[k] = v self.data[k] = v
def get(self, key, failobj=None): def get(self, key, failobj=None):
if self.data.has_key(key): if self.data.has_key(key):
return self.data[key] return self.data[key]
else: else:
return failobj return failobj
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment