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

The usual.

parent 65e53990
This diff is collapsed.
...@@ -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()
This diff is collapsed.
...@@ -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__':
......
This diff is collapsed.
...@@ -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)
......
This diff is collapsed.
# 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)
......
This diff is collapsed.
This diff is collapsed.
...@@ -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()
This diff is collapsed.
...@@ -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()
This diff is collapsed.
...@@ -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
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -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)
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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