The Usual

This commit is contained in:
Jeremy Hylton 2000-09-26 17:32:27 +00:00
parent 0872e05851
commit d635b1d724
20 changed files with 643 additions and 422 deletions

View File

@ -3,28 +3,31 @@
This module builds on SimpleHTTPServer by implementing GET and POST This module builds on SimpleHTTPServer by implementing GET and POST
requests to cgi-bin scripts. requests to cgi-bin scripts.
If the os.fork() function is not present, this module will not work; If the os.fork() function is not present (e.g. on Windows),
SystemError will be raised instead. os.popen2() is used as a fallback, with slightly altered semantics; if
that function is not present either (e.g. on Macintosh), only Python
scripts are supported, and they are executed by the current process.
In all cases, the implementation is intentionally naive -- all
requests are executed sychronously.
SECURITY WARNING: DON'T USE THIS CODE UNLESS YOU ARE INSIDE A FIREWALL
-- it may execute arbitrary Python code or external programs.
""" """
__version__ = "0.3" __version__ = "0.4"
import os import os
import sys
import string import string
import urllib import urllib
import BaseHTTPServer import BaseHTTPServer
import SimpleHTTPServer import SimpleHTTPServer
try:
os.fork
except AttributeError:
raise SystemError, __name__ + " requires os.fork()"
class CGIHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): class CGIHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
"""Complete HTTP server with GET, HEAD and POST commands. """Complete HTTP server with GET, HEAD and POST commands.
@ -35,6 +38,10 @@ class CGIHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
""" """
# Determine platform specifics
have_fork = hasattr(os, 'fork')
have_popen2 = hasattr(os, 'popen2')
# Make rfile unbuffered -- we need to read one line and then pass # Make rfile unbuffered -- we need to read one line and then pass
# the rest to a subprocess, so we can't use buffered input. # the rest to a subprocess, so we can't use buffered input.
rbufsize = 0 rbufsize = 0
@ -59,9 +66,9 @@ class CGIHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
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 self.path corresponds to a CGI script.
Return a tuple (dir, rest) if PATH requires running a Return a tuple (dir, rest) if self.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.
@ -83,6 +90,15 @@ class CGIHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
cgi_directories = ['/cgi-bin', '/htbin'] cgi_directories = ['/cgi-bin', '/htbin']
def is_executable(self, path):
"""Test whether argument path is an executable file."""
return executable(path)
def is_python(self, path):
"""Test whether argument path is a Python script."""
head, tail = os.path.splitext(path)
return tail.lower() in (".py", ".pyw")
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
@ -105,79 +121,152 @@ class CGIHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
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): ispy = self.is_python(scriptname)
self.send_error(403, "CGI script is not executable (%s)" % if not ispy:
`scriptname`) if not (self.have_fork or self.have_popen2):
return self.send_error(403, "CGI script is not a Python script (%s)" %
nobody = nobody_uid() `scriptname`)
self.send_response(200, "Script output follows") return
self.wfile.flush() # Always flush before forking if not self.is_executable(scriptfile):
pid = os.fork() self.send_error(403, "CGI script is not executable (%s)" %
if pid != 0: `scriptname`)
# Parent return
pid, sts = os.waitpid(pid, 0)
if sts: # Reference: http://hoohoo.ncsa.uiuc.edu/cgi/env.html
self.log_error("CGI script exit status x%x" % sts) # XXX Much of the following could be prepared ahead of time!
return env = {}
# Child env['SERVER_SOFTWARE'] = self.version_string()
try: env['SERVER_NAME'] = self.server.server_name
# Reference: http://hoohoo.ncsa.uiuc.edu/cgi/env.html env['GATEWAY_INTERFACE'] = 'CGI/1.1'
# XXX Much of the following could be prepared ahead of time! env['SERVER_PROTOCOL'] = self.protocol_version
env = {} env['SERVER_PORT'] = str(self.server.server_port)
env['SERVER_SOFTWARE'] = self.version_string() env['REQUEST_METHOD'] = self.command
env['SERVER_NAME'] = self.server.server_name uqrest = urllib.unquote(rest)
env['GATEWAY_INTERFACE'] = 'CGI/1.1' env['PATH_INFO'] = uqrest
env['SERVER_PROTOCOL'] = self.protocol_version env['PATH_TRANSLATED'] = self.translate_path(uqrest)
env['SERVER_PORT'] = str(self.server.server_port) env['SCRIPT_NAME'] = scriptname
env['REQUEST_METHOD'] = self.command if query:
uqrest = urllib.unquote(rest) env['QUERY_STRING'] = query
env['PATH_INFO'] = uqrest host = self.address_string()
env['PATH_TRANSLATED'] = self.translate_path(uqrest) if host != self.client_address[0]:
env['SCRIPT_NAME'] = scriptname env['REMOTE_HOST'] = host
if query: env['REMOTE_ADDR'] = self.client_address[0]
env['QUERY_STRING'] = query # XXX AUTH_TYPE
host = self.address_string() # XXX REMOTE_USER
if host != self.client_address[0]: # XXX REMOTE_IDENT
env['REMOTE_HOST'] = host if self.headers.typeheader is None:
env['REMOTE_ADDR'] = self.client_address[0] env['CONTENT_TYPE'] = self.headers.type
# AUTH_TYPE else:
# REMOTE_USER env['CONTENT_TYPE'] = self.headers.typeheader
# REMOTE_IDENT length = self.headers.getheader('content-length')
if self.headers.typeheader is None: if length:
env['CONTENT_TYPE'] = self.headers.type env['CONTENT_LENGTH'] = length
accept = []
for line in self.headers.getallmatchingheaders('accept'):
if line[:1] in string.whitespace:
accept.append(string.strip(line))
else: else:
env['CONTENT_TYPE'] = self.headers.typeheader accept = accept + string.split(line[7:], ',')
length = self.headers.getheader('content-length') env['HTTP_ACCEPT'] = string.joinfields(accept, ',')
if length: ua = self.headers.getheader('user-agent')
env['CONTENT_LENGTH'] = length if ua:
accept = [] env['HTTP_USER_AGENT'] = ua
for line in self.headers.getallmatchingheaders('accept'): co = filter(None, self.headers.getheaders('cookie'))
if line[:1] in string.whitespace: if co:
accept.append(string.strip(line)) env['HTTP_COOKIE'] = string.join(co, ', ')
else: # XXX Other HTTP_* headers
accept = accept + string.split(line[7:], ',') if not self.have_fork:
env['HTTP_ACCEPT'] = string.joinfields(accept, ',') # Since we're setting the env in the parent, provide empty
ua = self.headers.getheader('user-agent') # values to override previously set values
if ua: for k in ('QUERY_STRING', 'REMOTE_HOST', 'CONTENT_LENGTH',
env['HTTP_USER_AGENT'] = ua 'HTTP_USER_AGENT', 'HTTP_COOKIE'):
co = filter(None, self.headers.getheaders('cookie')) env.setdefault(k, "")
if co:
env['HTTP_COOKIE'] = string.join(co, ', ') self.send_response(200, "Script output follows")
# XXX Other HTTP_* headers
decoded_query = string.replace(query, '+', ' ') decoded_query = string.replace(query, '+', ' ')
if self.have_fork:
# Unix -- fork as we should
args = [script]
if '=' not in decoded_query:
args.append(decoded_query)
nobody = nobody_uid()
self.wfile.flush() # Always flush before forking
pid = os.fork()
if pid != 0:
# Parent
pid, sts = os.waitpid(pid, 0)
if sts:
self.log_error("CGI script exit status %#x", sts)
return
# Child
try: try:
os.setuid(nobody) try:
except os.error: os.setuid(nobody)
pass except os.error:
os.dup2(self.rfile.fileno(), 0) pass
os.dup2(self.wfile.fileno(), 1) os.dup2(self.rfile.fileno(), 0)
print scriptfile, script, decoded_query os.dup2(self.wfile.fileno(), 1)
os.execve(scriptfile, os.execve(scriptfile, args, env)
[script, decoded_query], except:
env) self.server.handle_error(self.request, self.client_address)
except: os._exit(127)
self.server.handle_error(self.request, self.client_address)
os._exit(127) elif self.have_popen2:
# Windows -- use popen2 to create a subprocess
import shutil
os.environ.update(env)
cmdline = scriptfile
if self.is_python(scriptfile):
interp = sys.executable
if interp.lower().endswith("w.exe"):
# On Windows, use python.exe, not python.exe
interp = interp[:-5] = interp[-4:]
cmdline = "%s %s" % (interp, cmdline)
if '=' not in query and '"' not in query:
cmdline = '%s "%s"' % (cmdline, query)
self.log_error("command: %s", cmdline)
try:
nbytes = int(length)
except:
nbytes = 0
fi, fo = os.popen2(cmdline)
if self.command.lower() == "post" and nbytes > 0:
data = self.rfile.read(nbytes)
fi.write(data)
fi.close()
shutil.copyfileobj(fo, self.wfile)
sts = fo.close()
if sts:
self.log_error("CGI script exit status %#x", sts)
else:
self.log_error("CGI script exited OK")
else:
# Other O.S. -- execute script in this process
os.environ.update(env)
save_argv = sys.argv
save_stdin = sys.stdin
save_stdout = sys.stdout
save_stderr = sys.stderr
try:
try:
sys.argv = [scriptfile]
if '=' not in decoded_query:
sys.argv.append(decoded_query)
sys.stdout = self.wfile
sys.stdin = self.rfile
execfile(scriptfile, {"__name__": "__main__"})
finally:
sys.argv = save_argv
sys.stdin = save_stdin
sys.stdout = save_stdout
sys.stderr = save_stderr
except SystemExit, sts:
self.log_error("CGI script exit status %s", str(sts))
else:
self.log_error("CGI script exited OK")
nobody = None nobody = None
@ -187,7 +276,10 @@ def nobody_uid():
global nobody global nobody
if nobody: if nobody:
return nobody return nobody
import pwd try:
import pwd
except ImportError:
return -1
try: try:
nobody = pwd.getpwnam('nobody')[2] nobody = pwd.getpwnam('nobody')[2]
except KeyError: except KeyError:

View File

@ -440,7 +440,7 @@ class ConfigParser:
# allow empty values # allow empty values
if optval == '""': if optval == '""':
optval = '' optval = ''
cursect[optname] = optval cursect[self.optionxform(optname)] = optval
else: else:
# a non-fatal parsing error occurred. set up the # a non-fatal parsing error occurred. set up the
# exception but keep going. the exception will be # exception but keep going. the exception will be

View File

@ -67,9 +67,6 @@ class _posixfile_:
(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):
self._file_.close()
# #
# Initialization routines # Initialization routines
# #

View File

@ -48,6 +48,11 @@ def compile(file, cfile=None, dfile=None):
except AttributeError: except AttributeError:
timestamp = long(os.stat(file)[8]) timestamp = long(os.stat(file)[8])
codestring = f.read() codestring = f.read()
# If parsing from a string, line breaks are \n (see parsetok.c:tok_nextc)
# Replace will return original string if pattern is not found, so
# we don't need to check whether it is found first.
codestring = codestring.replace("\r\n","\n")
codestring = codestring.replace("\r","\n")
f.close() f.close()
if codestring and codestring[-1] != '\n': if codestring and codestring[-1] != '\n':
codestring = codestring + '\n' codestring = codestring + '\n'

View File

@ -634,7 +634,7 @@ def parse_template(source, pattern):
while 1: while 1:
group = _group(this, pattern.groups+1) group = _group(this, pattern.groups+1)
if group: if group:
if (not s.next or if (s.next not in DIGITS or
not _group(this + s.next, pattern.groups+1)): not _group(this + s.next, pattern.groups+1)):
code = MARK, int(group) code = MARK, int(group)
break break

View File

@ -91,11 +91,15 @@ class StringIO:
r = self.buf[self.pos:newpos] r = self.buf[self.pos:newpos]
self.pos = newpos self.pos = newpos
return r return r
def readlines(self): def readlines(self, sizehint = 0):
total = 0
lines = [] lines = []
line = self.readline() line = self.readline()
while line: while line:
lines.append(line) lines.append(line)
total += len(line)
if 0 < sizehint <= total:
break
line = self.readline() line = self.readline()
return lines return lines
def write(self, s): def write(self, s):

View File

@ -122,9 +122,14 @@ def testtype(type, example):
a.pop() a.pop()
a.pop() a.pop()
a.pop() a.pop()
a.pop() x = a.pop()
if x != 'e':
raise TestFailed, "array(%s) pop-test" % `type`
if a != array.array(type, "acd"): if a != array.array(type, "acd"):
raise TestFailed, "array(%s) pop-test" % `type` raise TestFailed, "array(%s) pop-test" % `type`
a.reverse()
if a != array.array(type, "dca"):
raise TestFailed, "array(%s) reverse-test" % `type`
else: else:
a = array.array(type, [1, 2, 3, 4, 5]) a = array.array(type, [1, 2, 3, 4, 5])
a[:-1] = a a[:-1] = a
@ -155,9 +160,14 @@ def testtype(type, example):
a.pop() a.pop()
a.pop() a.pop()
a.pop() a.pop()
a.pop() x = a.pop()
if x != 5:
raise TestFailed, "array(%s) pop-test" % `type`
if a != array.array(type, [1, 3, 4]): if a != array.array(type, [1, 3, 4]):
raise TestFailed, "array(%s) pop-test" % `type` raise TestFailed, "array(%s) pop-test" % `type`
a.reverse()
if a != array.array(type, [4, 3, 1]):
raise TestFailed, "array(%s) reverse-test" % `type`
# test that overflow exceptions are raised as expected for assignment # test that overflow exceptions are raised as expected for assignment
# to array of specific integral types # to array of specific integral types

View File

@ -1,107 +1,5 @@
# Test the cPickle module # Test the cPickle module
DATA = """(lp0
I0
aL1L
aF2.0
ac__builtin__
complex
p1
(F3.0
F0.0
tp2
Rp3
a(S'abc'
p4
g4
(i__main__
C
p5
(dp6
S'foo'
p7
I1
sS'bar'
p8
I2
sbg5
tp9
ag9
aI5
a.
"""
BINDATA = ']q\000(K\000L1L\012G@\000\000\000\000\000\000\000c__builtin__\012complex\012q\001(G@\010\000\000\000\000\000\000G\000\000\000\000\000\000\000\000tq\002Rq\003(U\003abcq\004h\004(c__main__\012C\012q\005oq\006}q\007(U\003fooq\010K\001U\003barq\011K\002ubh\006tq\012h\012K\005e.'
import cPickle import cPickle
import test_pickle
class C: test_pickle.dotest(cPickle)
def __cmp__(self, other):
return cmp(self.__dict__, other.__dict__)
import __main__
__main__.C = C
def dotest():
c = C()
c.foo = 1
c.bar = 2
x = [0, 1L, 2.0, 3.0+0j]
y = ('abc', 'abc', c, c)
x.append(y)
x.append(y)
x.append(5)
print "dumps()"
s = cPickle.dumps(x)
print "loads()"
x2 = cPickle.loads(s)
if x2 == x: print "ok"
else: print "bad"
print "loads() DATA"
x2 = cPickle.loads(DATA)
if x2 == x: print "ok"
else: print "bad"
print "dumps() binary"
s = cPickle.dumps(x, 1)
print "loads() binary"
x2 = cPickle.loads(s)
if x2 == x: print "ok"
else: print "bad"
print "loads() BINDATA"
x2 = cPickle.loads(BINDATA)
if x2 == x: print "ok"
else: print "bad"
# Test protection against closed files
import tempfile, os
fn = tempfile.mktemp()
f = open(fn, "w")
f.close()
try:
cPickle.dump(123, f)
except ValueError:
pass
else:
print "dump to closed file should raise ValueError"
f = open(fn, "r")
f.close()
try:
cPickle.load(f)
except ValueError:
pass
else:
print "load from closed file should raise ValueError"
os.remove(fn)
# Test specific bad cases
for i in range(10):
try:
x = cPickle.loads('garyp')
except cPickle.BadPickleGet, y:
del y
else:
print "unexpected success!"
break
dotest()

View File

@ -86,6 +86,55 @@ r(SyntaxError)
try: exec '/\n' try: exec '/\n'
except SyntaxError: pass except SyntaxError: pass
# make sure the right exception message is raised for each of these
# code fragments:
def ckmsg(src, msg):
try:
compile(src, '<fragment>', 'exec')
except SyntaxError, e:
print e.msg
if e.msg == msg:
print "ok"
else:
print "expected:", msg
else:
print "failed to get expected SyntaxError"
s = '''\
while 1:
try:
continue
except:
pass
'''
ckmsg(s, "'continue' not supported inside 'try' clause")
s = '''\
while 1:
try:
continue
finally:
pass
'''
ckmsg(s, "'continue' not supported inside 'try' clause")
s = '''\
while 1:
try:
if 1:
continue
finally:
pass
'''
ckmsg(s, "'continue' not supported inside 'try' clause")
s = '''\
try:
continue
except:
pass
'''
ckmsg(s, "'continue' not properly in loop")
ckmsg("continue\n", "'continue' not properly in loop")
r(IndentationError) r(IndentationError)
r(TabError) r(TabError)

View File

@ -21,7 +21,7 @@ if sys.platform in ('netbsd1',
'bsdos2', 'bsdos3', 'bsdos4', 'bsdos2', 'bsdos3', 'bsdos4',
'openbsd', 'openbsd2'): 'openbsd', 'openbsd2'):
lockdata = struct.pack('lxxxxlxxxxlhh', 0, 0, 0, FCNTL.F_WRLCK, 0) lockdata = struct.pack('lxxxxlxxxxlhh', 0, 0, 0, FCNTL.F_WRLCK, 0)
elif sys.platform in ['aix3', 'aix4']: elif sys.platform in ['aix3', 'aix4', 'hp-uxB']:
lockdata = struct.pack('hhlllii', FCNTL.F_WRLCK, 0, 0, 0, 0, 0, 0) lockdata = struct.pack('hhlllii', FCNTL.F_WRLCK, 0, 0, 0, 0, 0, 0)
else: else:
lockdata = struct.pack('hhllhh', FCNTL.F_WRLCK, 0, 0, 0, 0, 0) lockdata = struct.pack('hhllhh', FCNTL.F_WRLCK, 0, 0, 0, 0, 0)

View File

@ -355,6 +355,13 @@ def f():
del z del z
exec 'z=1+1' exec 'z=1+1'
if z <> 2: raise TestFailed, 'exec \'z=1+1\'' if z <> 2: raise TestFailed, 'exec \'z=1+1\''
z = None
del z
exec u'z=1+1\n'
if z <> 2: raise TestFailed, 'exec u\'z=1+1\'\\n'
del z
exec u'z=1+1'
if z <> 2: raise TestFailed, 'exec u\'z=1+1\''
f() f()
g = {} g = {}
exec 'z = 1' in g exec 'z = 1' in g

View File

@ -5,6 +5,7 @@ from xml.dom.minidom import parse, Node, Document, parseString
import os.path import os.path
import sys import sys
import traceback import traceback
from test_support import verbose
if __name__ == "__main__": if __name__ == "__main__":
base = sys.argv[0] base = sys.argv[0]
@ -13,15 +14,28 @@ else:
tstfile = os.path.join(os.path.dirname(base), "test.xml") tstfile = os.path.join(os.path.dirname(base), "test.xml")
del base del base
def confirm( test, testname="Test" ):
if test:
print "Passed " + testname
else:
print "Failed " + testname
raise Exception
Node._debug=1 Node._debug=1
def testParseFromFile():
from StringIO import StringIO
dom=parse( StringIO( open( tstfile ).read() ) )
dom.unlink()
confirm(isinstance(dom,Document))
def testGetElementsByTagName( ): def testGetElementsByTagName( ):
dom=parse( tstfile ) dom=parse( tstfile )
assert dom.getElementsByTagName( "LI" )==\ confirm( dom.getElementsByTagName( "LI" )==\
dom.documentElement.getElementsByTagName( "LI" ) dom.documentElement.getElementsByTagName( "LI" ) )
dom.unlink() dom.unlink()
dom=None dom=None
assert( len( Node.allnodes ))==0 confirm (len( Node.allnodes )==0)
def testInsertBefore( ): def testInsertBefore( ):
dom=parse( tstfile ) dom=parse( tstfile )
@ -32,44 +46,44 @@ def testInsertBefore( ):
#docel.insertBefore( dom.createProcessingInstruction("a", "b"), #docel.insertBefore( dom.createProcessingInstruction("a", "b"),
# docel.childNodes[0]) # docel.childNodes[0])
#assert docel.childNodes[0].target=="a" #confirm( docel.childNodes[0].tet=="a" )
#assert docel.childNodes[2].target=="a" #confirm( docel.childNodes[2].tet=="a" )
dom.unlink() dom.unlink()
del dom del dom
del docel del docel
assert( len( Node.allnodes ))==0 confirm( len( Node.allnodes )==0)
def testAppendChild(): def testAppendChild():
dom=parse( tstfile ) dom=parse( tstfile )
dom.documentElement.appendChild( dom.createComment( u"Hello" )) dom.documentElement.appendChild( dom.createComment( u"Hello" ))
assert dom.documentElement.childNodes[-1].nodeName=="#comment" confirm( dom.documentElement.childNodes[-1].nodeName=="#comment" )
assert dom.documentElement.childNodes[-1].data=="Hello" confirm( dom.documentElement.childNodes[-1].data=="Hello" )
dom.unlink() dom.unlink()
dom=None dom=None
assert( len( Node.allnodes ))==0 confirm( len( Node.allnodes )==0 )
def testNonZero(): def testNonZero():
dom=parse( tstfile ) dom=parse( tstfile )
assert dom # should not be zero confirm( dom )# should not be zero
dom.appendChild( dom.createComment( "foo" ) ) dom.appendChild( dom.createComment( "foo" ) )
assert not dom.childNodes[-1].childNodes confirm( not dom.childNodes[-1].childNodes )
dom.unlink() dom.unlink()
dom=None dom=None
assert( len( Node.allnodes ))==0 confirm( len( Node.allnodes )==0 )
def testUnlink(): def testUnlink():
dom=parse( tstfile ) dom=parse( tstfile )
dom.unlink() dom.unlink()
dom=None dom=None
assert( len( Node.allnodes ))==0 confirm( len( Node.allnodes )==0 )
def testElement(): def testElement():
dom=Document() dom=Document()
dom.appendChild( dom.createElement( "abc" ) ) dom.appendChild( dom.createElement( "abc" ) )
assert dom.documentElement confirm( dom.documentElement )
dom.unlink() dom.unlink()
dom=None dom=None
assert( len( Node.allnodes ))==0 confirm( len( Node.allnodes )==0 )
def testAAA(): def testAAA():
dom=parseString( "<abc/>" ) dom=parseString( "<abc/>" )
@ -91,20 +105,20 @@ def testAddAttr():
child=dom.appendChild( dom.createElement( "abc" ) ) child=dom.appendChild( dom.createElement( "abc" ) )
child.setAttribute( "def", "ghi" ) child.setAttribute( "def", "ghi" )
assert child.getAttribute( "def" )=="ghi" confirm( child.getAttribute( "def" )=="ghi" )
assert child.attributes["def"].value=="ghi" confirm( child.attributes["def"].value=="ghi" )
child.setAttribute( "jkl", "mno" ) child.setAttribute( "jkl", "mno" )
assert child.getAttribute( "jkl" )=="mno" confirm( child.getAttribute( "jkl" )=="mno" )
assert child.attributes["jkl"].value=="mno" confirm( child.attributes["jkl"].value=="mno" )
assert len( child.attributes )==2 confirm( len( child.attributes )==2 )
child.setAttribute( "def", "newval" ) child.setAttribute( "def", "newval" )
assert child.getAttribute( "def" )=="newval" confirm( child.getAttribute( "def" )=="newval" )
assert child.attributes["def"].value=="newval" confirm( child.attributes["def"].value=="newval" )
assert len( child.attributes )==2 confirm( len( child.attributes )==2 )
dom.unlink() dom.unlink()
dom=None dom=None
@ -114,22 +128,22 @@ def testDeleteAttr():
dom=Document() dom=Document()
child=dom.appendChild( dom.createElement( "abc" ) ) child=dom.appendChild( dom.createElement( "abc" ) )
assert len( child.attributes)==0 confirm( len( child.attributes)==0 )
child.setAttribute( "def", "ghi" ) child.setAttribute( "def", "ghi" )
assert len( child.attributes)==1 confirm( len( child.attributes)==1 )
del child.attributes["def"] del child.attributes["def"]
assert len( child.attributes)==0 confirm( len( child.attributes)==0 )
dom.unlink() dom.unlink()
assert( len( Node.allnodes ))==0 confirm( len( Node.allnodes )==0 )
def testRemoveAttr(): def testRemoveAttr():
dom=Document() dom=Document()
child=dom.appendChild( dom.createElement( "abc" ) ) child=dom.appendChild( dom.createElement( "abc" ) )
child.setAttribute( "def", "ghi" ) child.setAttribute( "def", "ghi" )
assert len( child.attributes)==1 confirm( len( child.attributes)==1 )
child.removeAttribute("def" ) child.removeAttribute("def" )
assert len( child.attributes)==0 confirm( len( child.attributes)==0 )
dom.unlink() dom.unlink()
@ -140,9 +154,9 @@ def testRemoveAttrNS():
child.setAttributeNS( "http://www.w3.org", "xmlns:python", child.setAttributeNS( "http://www.w3.org", "xmlns:python",
"http://www.python.org" ) "http://www.python.org" )
child.setAttributeNS( "http://www.python.org", "python:abcattr", "foo" ) child.setAttributeNS( "http://www.python.org", "python:abcattr", "foo" )
assert len( child.attributes )==2 confirm( len( child.attributes )==2 )
child.removeAttributeNS( "http://www.python.org", "abcattr" ) child.removeAttributeNS( "http://www.python.org", "abcattr" )
assert len( child.attributes )==1 confirm( len( child.attributes )==1 )
dom.unlink() dom.unlink()
dom=None dom=None
@ -151,31 +165,31 @@ def testRemoveAttributeNode():
dom=Document() dom=Document()
child=dom.appendChild( dom.createElement( "foo" ) ) child=dom.appendChild( dom.createElement( "foo" ) )
child.setAttribute( "spam", "jam" ) child.setAttribute( "spam", "jam" )
assert len( child.attributes )==1 confirm( len( child.attributes )==1 )
node=child.getAttributeNode( "spam" ) node=child.getAttributeNode( "spam" )
child.removeAttributeNode( node ) child.removeAttributeNode( node )
assert len( child.attributes )==0 confirm( len( child.attributes )==0 )
dom.unlink() dom.unlink()
dom=None dom=None
assert len( Node.allnodes )==0 confirm( len( Node.allnodes )==0 )
def testChangeAttr(): def testChangeAttr():
dom=parseString( "<abc/>" ) dom=parseString( "<abc/>" )
el=dom.documentElement el=dom.documentElement
el.setAttribute( "spam", "jam" ) el.setAttribute( "spam", "jam" )
assert len( el.attributes )==1 confirm( len( el.attributes )==1 )
el.setAttribute( "spam", "bam" ) el.setAttribute( "spam", "bam" )
assert len( el.attributes )==1 confirm( len( el.attributes )==1 )
el.attributes["spam"]="ham" el.attributes["spam"]="ham"
assert len( el.attributes )==1 confirm( len( el.attributes )==1 )
el.setAttribute( "spam2", "bam" ) el.setAttribute( "spam2", "bam" )
assert len( el.attributes )==2 confirm( len( el.attributes )==2 )
el.attributes[ "spam2"]= "bam2" el.attributes[ "spam2"]= "bam2"
assert len( el.attributes )==2 confirm( len( el.attributes )==2 )
dom.unlink() dom.unlink()
dom=None dom=None
assert len( Node.allnodes )==0 confirm( len( Node.allnodes )==0 )
def testGetAttrList(): def testGetAttrList():
pass pass
@ -199,7 +213,7 @@ def testElementReprAndStr():
el=dom.appendChild( dom.createElement( "abc" ) ) el=dom.appendChild( dom.createElement( "abc" ) )
string1=repr( el ) string1=repr( el )
string2=str( el ) string2=str( el )
assert string1==string2 confirm( string1==string2 )
dom.unlink() dom.unlink()
# commented out until Fredrick's fix is checked in # commented out until Fredrick's fix is checked in
@ -208,25 +222,25 @@ def _testElementReprAndStrUnicode():
el=dom.appendChild( dom.createElement( u"abc" ) ) el=dom.appendChild( dom.createElement( u"abc" ) )
string1=repr( el ) string1=repr( el )
string2=str( el ) string2=str( el )
assert string1==string2 confirm( string1==string2 )
dom.unlink() dom.unlink()
# commented out until Fredrick's fix is checked in # commented out until Fredrick's fix is checked in
def _testElementReprAndStrUnicodeNS(): def _testElementReprAndStrUnicodeNS():
dom=Document() dom=Document()
el=dom.appendChild( el=dom.appendChild(
dom.createElementNS( u"http://www.slashdot.org", u"slash:abc" )) dom.createElementNS( u"http://www.slashdot.org", u"slash:abc" ))
string1=repr( el ) string1=repr( el )
string2=str( el ) string2=str( el )
assert string1==string2 confirm( string1==string2 )
assert string1.find("slash:abc" )!=-1 confirm( string1.find("slash:abc" )!=-1 )
dom.unlink() dom.unlink()
def testAttributeRepr(): def testAttributeRepr():
dom=Document() dom=Document()
el=dom.appendChild( dom.createElement( u"abc" ) ) el=dom.appendChild( dom.createElement( u"abc" ) )
node=el.setAttribute( "abc", "def" ) node=el.setAttribute( "abc", "def" )
assert str( node ) == repr( node ) confirm( str( node ) == repr( node ) )
dom.unlink() dom.unlink()
def testTextNodeRepr(): pass def testTextNodeRepr(): pass
@ -312,6 +326,9 @@ def testClonePIDeep(): pass
names=globals().keys() names=globals().keys()
names.sort() names.sort()
works=1
for name in names: for name in names:
if name.startswith( "test" ): if name.startswith( "test" ):
func=globals()[name] func=globals()[name]
@ -320,12 +337,24 @@ for name in names:
print "Test Succeeded", name print "Test Succeeded", name
if len( Node.allnodes ): if len( Node.allnodes ):
print "Garbage left over:" print "Garbage left over:"
print Node.allnodes.items()[0:10] if verbose:
print Node.allnodes.items()[0:10]
else:
# Don't print specific nodes if repeatable results
# are needed
print len(Node.allnodes)
Node.allnodes={} Node.allnodes={}
except Exception, e : except Exception, e :
works=0
print "Test Failed: ", name print "Test Failed: ", name
apply( traceback.print_exception, sys.exc_info() ) apply( traceback.print_exception, sys.exc_info() )
print `e` print `e`
Node.allnodes={} Node.allnodes={}
raise
if works:
print "All tests succeeded"
else:
print "\n\n\n\n************ Check for failures!"
Node.debug = None # Delete debug output collected in a StringIO object
Node._debug = 0 # And reset debug mode

View File

@ -1,5 +1,6 @@
# Test the pickle module # Test the pickle module
# break into multiple strings to please font-lock-mode
DATA = """(lp0 DATA = """(lp0
I0 I0
aL1L aL1L
@ -7,17 +8,20 @@ aF2.0
ac__builtin__ ac__builtin__
complex complex
p1 p1
(F3.0 """ \
"""(F3.0
F0.0 F0.0
tp2 tp2
Rp3 Rp3
a(S'abc' a(S'abc'
p4 p4
g4 g4
(i__main__ """ \
"""(i__main__
C C
p5 p5
(dp6 """ \
"""(dp6
S'foo' S'foo'
p7 p7
I1 I1
@ -33,8 +37,6 @@ a.
BINDATA = ']q\000(K\000L1L\012G@\000\000\000\000\000\000\000c__builtin__\012complex\012q\001(G@\010\000\000\000\000\000\000G\000\000\000\000\000\000\000\000tq\002Rq\003(U\003abcq\004h\004(c__main__\012C\012q\005oq\006}q\007(U\003fooq\010K\001U\003barq\011K\002ubh\006tq\012h\012K\005e.' BINDATA = ']q\000(K\000L1L\012G@\000\000\000\000\000\000\000c__builtin__\012complex\012q\001(G@\010\000\000\000\000\000\000G\000\000\000\000\000\000\000\000tq\002Rq\003(U\003abcq\004h\004(c__main__\012C\012q\005oq\006}q\007(U\003fooq\010K\001U\003barq\011K\002ubh\006tq\012h\012K\005e.'
import pickle
class C: class C:
def __cmp__(self, other): def __cmp__(self, other):
return cmp(self.__dict__, other.__dict__) return cmp(self.__dict__, other.__dict__)
@ -42,7 +44,7 @@ class C:
import __main__ import __main__
__main__.C = C __main__.C = C
def dotest(): def dotest(pickle):
c = C() c = C()
c.foo = 1 c.foo = 1
c.bar = 2 c.bar = 2
@ -51,6 +53,8 @@ def dotest():
x.append(y) x.append(y)
x.append(y) x.append(y)
x.append(5) x.append(5)
r = []
r.append(r)
print "dumps()" print "dumps()"
s = pickle.dumps(x) s = pickle.dumps(x)
print "loads()" print "loads()"
@ -71,5 +75,69 @@ def dotest():
x2 = pickle.loads(BINDATA) x2 = pickle.loads(BINDATA)
if x2 == x: print "ok" if x2 == x: print "ok"
else: print "bad" else: print "bad"
s = pickle.dumps(r)
print "dumps() RECURSIVE"
x2 = pickle.loads(s)
if x2 == r: print "ok"
else: print "bad"
# don't create cyclic garbage
del x2[0]
del r[0]
dotest() # Test protection against closed files
import tempfile, os
fn = tempfile.mktemp()
f = open(fn, "w")
f.close()
try:
pickle.dump(123, f)
except ValueError:
pass
else:
print "dump to closed file should raise ValueError"
f = open(fn, "r")
f.close()
try:
pickle.load(f)
except ValueError:
pass
else:
print "load from closed file should raise ValueError"
os.remove(fn)
# Test specific bad cases
for i in range(10):
try:
x = pickle.loads('garyp')
except KeyError, y:
# pickle
del y
except pickle.BadPickleGet, y:
# cPickle
del y
else:
print "unexpected success!"
break
# Test insecure strings
insecure = ["abc", "2 + 2", # not quoted
"'abc' + 'def'", # not a single quoted string
"'abc", # quote is not closed
"'abc\"", # open quote and close quote don't match
"'abc' ?", # junk after close quote
# some tests of the quoting rules
"'abc\"\''",
"'\\\\a\'\'\'\\\'\\\\\''",
]
for s in insecure:
buf = "S" + s + "\012p0\012."
try:
x = pickle.loads(buf)
except ValueError:
pass
else:
print "accepted insecure string: %s" % repr(buf)
import pickle
dotest(pickle)

View File

@ -3,10 +3,7 @@
# XXX TypeErrors on calling handlers, or on bad return values from a # XXX TypeErrors on calling handlers, or on bad return values from a
# handler, are obscure and unhelpful. # handler, are obscure and unhelpful.
import sys, string from xml.parsers import expat
import os
import pyexpat
class Outputter: class Outputter:
def StartElementHandler(self, name, attrs): def StartElementHandler(self, name, attrs):
@ -16,7 +13,7 @@ class Outputter:
print 'End element:\n\t', repr(name) print 'End element:\n\t', repr(name)
def CharacterDataHandler(self, data): def CharacterDataHandler(self, data):
data = string.strip(data) data = data.strip()
if data: if data:
print 'Character data:' print 'Character data:'
print '\t', repr(data) print '\t', repr(data)
@ -63,29 +60,37 @@ class Outputter:
pass pass
def confirm(ok):
if ok:
print "OK."
else:
print "Not OK."
out = Outputter() out = Outputter()
parser = pyexpat.ParserCreate(namespace_separator='!') parser = expat.ParserCreate(namespace_separator='!')
# Test getting/setting returns_unicode # Test getting/setting returns_unicode
parser.returns_unicode = 0 ; assert parser.returns_unicode == 0 parser.returns_unicode = 0; confirm(parser.returns_unicode == 0)
parser.returns_unicode = 1 ; assert parser.returns_unicode == 1 parser.returns_unicode = 1; confirm(parser.returns_unicode == 1)
parser.returns_unicode = 2 ; assert parser.returns_unicode == 1 parser.returns_unicode = 2; confirm(parser.returns_unicode == 1)
parser.returns_unicode = 0 ; assert parser.returns_unicode == 0 parser.returns_unicode = 0; confirm(parser.returns_unicode == 0)
HANDLER_NAMES = ['StartElementHandler', 'EndElementHandler', HANDLER_NAMES = [
'CharacterDataHandler', 'ProcessingInstructionHandler', 'StartElementHandler', 'EndElementHandler',
'UnparsedEntityDeclHandler', 'NotationDeclHandler', 'CharacterDataHandler', 'ProcessingInstructionHandler',
'StartNamespaceDeclHandler', 'EndNamespaceDeclHandler', 'UnparsedEntityDeclHandler', 'NotationDeclHandler',
'CommentHandler', 'StartCdataSectionHandler', 'StartNamespaceDeclHandler', 'EndNamespaceDeclHandler',
'EndCdataSectionHandler', 'CommentHandler', 'StartCdataSectionHandler',
'DefaultHandler', 'DefaultHandlerExpand', 'EndCdataSectionHandler',
#'NotStandaloneHandler', 'DefaultHandler', 'DefaultHandlerExpand',
'ExternalEntityRefHandler' #'NotStandaloneHandler',
] 'ExternalEntityRefHandler'
]
for name in HANDLER_NAMES: for name in HANDLER_NAMES:
setattr(parser, name, getattr(out, name) ) setattr(parser, name, getattr(out, name))
data = """<?xml version="1.0" encoding="iso-8859-1" standalone="no"?> data = '''\
<?xml version="1.0" encoding="iso-8859-1" standalone="no"?>
<?xml-stylesheet href="stylesheet.css"?> <?xml-stylesheet href="stylesheet.css"?>
<!-- comment data --> <!-- comment data -->
<!DOCTYPE quotations SYSTEM "quotations.dtd" [ <!DOCTYPE quotations SYSTEM "quotations.dtd" [
@ -104,45 +109,44 @@ data = """<?xml version="1.0" encoding="iso-8859-1" standalone="no"?>
<sub2><![CDATA[contents of CDATA section]]></sub2> <sub2><![CDATA[contents of CDATA section]]></sub2>
&external_entity; &external_entity;
</root> </root>
""" '''
# Produce UTF-8 output # Produce UTF-8 output
parser.returns_unicode = 0 parser.returns_unicode = 0
try: try:
parser.Parse(data, 1) parser.Parse(data, 1)
except pyexpat.error: except expat.error:
print '** Error', parser.ErrorCode, pyexpat.ErrorString( parser.ErrorCode) print '** Error', parser.ErrorCode, expat.ErrorString(parser.ErrorCode)
print '** Line', parser.ErrorLineNumber print '** Line', parser.ErrorLineNumber
print '** Column', parser.ErrorColumnNumber print '** Column', parser.ErrorColumnNumber
print '** Byte', parser.ErrorByteIndex print '** Byte', parser.ErrorByteIndex
# Try the parse again, this time producing Unicode output # Try the parse again, this time producing Unicode output
parser = pyexpat.ParserCreate(namespace_separator='!') parser = expat.ParserCreate(namespace_separator='!')
parser.returns_unicode = 1 parser.returns_unicode = 1
for name in HANDLER_NAMES: for name in HANDLER_NAMES:
setattr(parser, name, getattr(out, name) ) setattr(parser, name, getattr(out, name))
try: try:
parser.Parse(data, 1) parser.Parse(data, 1)
except pyexpat.error: except expat.error:
print '** Error', parser.ErrorCode, pyexpat.ErrorString( parser.ErrorCode) print '** Error', parser.ErrorCode, expat.ErrorString(parser.ErrorCode)
print '** Line', parser.ErrorLineNumber print '** Line', parser.ErrorLineNumber
print '** Column', parser.ErrorColumnNumber print '** Column', parser.ErrorColumnNumber
print '** Byte', parser.ErrorByteIndex print '** Byte', parser.ErrorByteIndex
# Try parsing a file # Try parsing a file
parser = pyexpat.ParserCreate(namespace_separator='!') parser = expat.ParserCreate(namespace_separator='!')
parser.returns_unicode = 1 parser.returns_unicode = 1
for name in HANDLER_NAMES: for name in HANDLER_NAMES:
setattr(parser, name, getattr(out, name) ) setattr(parser, name, getattr(out, name))
import StringIO import StringIO
file = StringIO.StringIO(data) file = StringIO.StringIO(data)
try: try:
parser.ParseFile(file) parser.ParseFile(file)
except pyexpat.error: except expat.error:
print '** Error', parser.ErrorCode, pyexpat.ErrorString( parser.ErrorCode) print '** Error', parser.ErrorCode, expat.ErrorString(parser.ErrorCode)
print '** Line', parser.ErrorLineNumber print '** Line', parser.ErrorLineNumber
print '** Column', parser.ErrorColumnNumber print '** Column', parser.ErrorColumnNumber
print '** Byte', parser.ErrorByteIndex print '** Byte', parser.ErrorByteIndex

View File

@ -120,3 +120,7 @@ Date: Wed, 13 Jan 1999 23:57:35 -0500
test''', [('', 'goit@lip.com')]) test''', [('', 'goit@lip.com')])
test('''To: guido@[132.151.1.21]
foo''', [('', 'guido@[132.151.1.21]')])

View File

@ -1,134 +1,15 @@
#! /usr/bin/env python # Tests StringIO and cStringIO
# Sanity checker for time.strftime import string
import time, calendar, sys, string, os, re def do_test(module):
from test_support import verbose s = (string.letters+'\n')*5
f = module.StringIO(s)
print f.read(10)
print f.readline()
print len(f.readlines(60))
def main(): # Don't bother testing cStringIO without
global verbose import StringIO, cStringIO
now = time.time() do_test(StringIO)
strftest(now) do_test(cStringIO)
verbose = 0
# Try a bunch of dates and times, chosen to vary through time of
# day and daylight saving time
for j in range(-5, 5):
for i in range(25):
strftest(now + (i + j*100)*23*3603)
def strftest(now):
if verbose:
print "strftime test for", time.ctime(now)
nowsecs = str(long(now))[:-1]
gmt = time.gmtime(now)
now = time.localtime(now)
if now[3] < 12: ampm='AM'
else: ampm='PM'
jan1 = time.localtime(time.mktime((now[0], 1, 1) + (0,)*6))
try:
if now[8]: tz = time.tzname[1]
else: tz = time.tzname[0]
except AttributeError:
tz = ''
if now[3] > 12: clock12 = now[3] - 12
elif now[3] > 0: clock12 = now[3]
else: clock12 = 12
expectations = (
('%a', calendar.day_abbr[now[6]], 'abbreviated weekday name'),
('%A', calendar.day_name[now[6]], 'full weekday name'),
('%b', calendar.month_abbr[now[1]], 'abbreviated month name'),
('%B', calendar.month_name[now[1]], 'full month name'),
# %c see below
('%d', '%02d' % now[2], 'day of month as number (00-31)'),
('%H', '%02d' % now[3], 'hour (00-23)'),
('%I', '%02d' % clock12, 'hour (01-12)'),
('%j', '%03d' % now[7], 'julian day (001-366)'),
('%m', '%02d' % now[1], 'month as number (01-12)'),
('%M', '%02d' % now[4], 'minute, (00-59)'),
('%p', ampm, 'AM or PM as appropriate'),
('%S', '%02d' % now[5], 'seconds of current time (00-60)'),
('%U', '%02d' % ((now[7] + jan1[6])/7),
'week number of the year (Sun 1st)'),
('%w', '0?%d' % ((1+now[6]) % 7), 'weekday as a number (Sun 1st)'),
('%W', '%02d' % ((now[7] + (jan1[6] - 1)%7)/7),
'week number of the year (Mon 1st)'),
# %x see below
('%X', '%02d:%02d:%02d' % (now[3], now[4], now[5]), '%H:%M:%S'),
('%y', '%02d' % (now[0]%100), 'year without century'),
('%Y', '%d' % now[0], 'year with century'),
# %Z see below
('%%', '%', 'single percent sign'),
)
nonstandard_expectations = (
# These are standard but don't have predictable output
('%c', fixasctime(time.asctime(now)), 'near-asctime() format'),
('%x', '%02d/%02d/%02d' % (now[1], now[2], (now[0]%100)),
'%m/%d/%y %H:%M:%S'),
('%Z', '%s' % tz, 'time zone name'),
# These are some platform specific extensions
('%D', '%02d/%02d/%02d' % (now[1], now[2], (now[0]%100)), 'mm/dd/yy'),
('%e', '%2d' % now[2], 'day of month as number, blank padded ( 0-31)'),
('%h', calendar.month_abbr[now[1]], 'abbreviated month name'),
('%k', '%2d' % now[3], 'hour, blank padded ( 0-23)'),
('%n', '\n', 'newline character'),
('%r', '%02d:%02d:%02d %s' % (clock12, now[4], now[5], ampm),
'%I:%M:%S %p'),
('%R', '%02d:%02d' % (now[3], now[4]), '%H:%M'),
('%s', nowsecs, 'seconds since the Epoch in UCT'),
('%t', '\t', 'tab character'),
('%T', '%02d:%02d:%02d' % (now[3], now[4], now[5]), '%H:%M:%S'),
('%3y', '%03d' % (now[0]%100),
'year without century rendered using fieldwidth'),
)
if verbose:
print "Strftime test, platform: %s, Python version: %s" % \
(sys.platform, string.split(sys.version)[0])
for e in expectations:
try:
result = time.strftime(e[0], now)
except ValueError, error:
print "Standard '%s' format gave error:" % e[0], error
continue
if re.match(e[1], result): continue
if not result or result[0] == '%':
print "Does not support standard '%s' format (%s)" % (e[0], e[2])
else:
print "Conflict for %s (%s):" % (e[0], e[2])
print " Expected %s, but got %s" % (e[1], result)
for e in nonstandard_expectations:
try:
result = time.strftime(e[0], now)
except ValueError, result:
if verbose:
print "Error for nonstandard '%s' format (%s): %s" % \
(e[0], e[2], str(result))
continue
if re.match(e[1], result):
if verbose:
print "Supports nonstandard '%s' format (%s)" % (e[0], e[2])
elif not result or result[0] == '%':
if verbose:
print "Does not appear to support '%s' format (%s)" % (e[0],
e[2])
else:
if verbose:
print "Conflict for nonstandard '%s' format (%s):" % (e[0],
e[2])
print " Expected %s, but got %s" % (e[1], result)
def fixasctime(s):
if s[8] == ' ':
s = s[:8] + '0' + s[9:]
return s
main()

View File

@ -0,0 +1,32 @@
# Minimal test of the quote function
import urllib
chars = 'abcdefghijklmnopqrstuvwxyz'\
'\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356' \
'\357\360\361\362\363\364\365\366\370\371\372\373\374\375\376\377' \
'ABCDEFGHIJKLMNOPQRSTUVWXYZ' \
'\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317' \
'\320\321\322\323\324\325\326\330\331\332\333\334\335\336'
expected = 'abcdefghijklmnopqrstuvwxyz%df%e0%e1%e2%e3%e4%e5%e6%e7%e8%e9%ea%eb%ec%ed%ee%ef%f0%f1%f2%f3%f4%f5%f6%f8%f9%fa%fb%fc%fd%fe%ffABCDEFGHIJKLMNOPQRSTUVWXYZ%c0%c1%c2%c3%c4%c5%c6%c7%c8%c9%ca%cb%cc%cd%ce%cf%d0%d1%d2%d3%d4%d5%d6%d8%d9%da%db%dc%dd%de'
test = urllib.quote(chars)
assert test == expected, "urllib.quote problem"
test2 = urllib.unquote(expected)
assert test2 == chars
in1 = "abc/def"
out1_1 = "abc/def"
out1_2 = "abc%2fdef"
assert urllib.quote(in1) == out1_1, "urllib.quote problem"
assert urllib.quote(in1, '') == out1_2, "urllib.quote problem"
in2 = "abc?def"
out2_1 = "abc%3fdef"
out2_2 = "abc?def"
assert urllib.quote(in2) == out2_1, "urllib.quote problem"
assert urllib.quote(in2, '?') == out2_2, "urllib.quote problem"

View File

@ -1,7 +1,147 @@
# Ridiculously simple test of the winsound module for Windows. # Test the windows specific win32reg module.
# Only win32reg functions not hit here: FlushKey, LoadKey and SaveKey
import winsound from _winreg import *
for i in range(100, 2000, 100): import os, sys
winsound.Beep(i, 75)
print "Hopefully you heard some sounds increasing in frequency!" test_key_name = "SOFTWARE\\Python Registry Test Key - Delete Me"
test_data = [
("Int Value", 45, REG_DWORD),
("String Val", "A string value", REG_SZ,),
(u"Unicode Val", u"A Unicode value", REG_SZ,),
("StringExpand", "The path is %path%", REG_EXPAND_SZ),
("UnicodeExpand", u"The path is %path%", REG_EXPAND_SZ),
("Multi-string", ["Lots", "of", "string", "values"], REG_MULTI_SZ),
("Multi-unicode", [u"Lots", u"of", u"unicode", u"values"], REG_MULTI_SZ),
("Multi-mixed", [u"Unicode", u"and", "string", "values"],REG_MULTI_SZ),
("Raw Data", ("binary"+chr(0)+"data"), REG_BINARY),
]
def WriteTestData(root_key):
# Set the default value for this key.
SetValue(root_key, test_key_name, REG_SZ, "Default value")
key = CreateKey(root_key, test_key_name)
# Create a sub-key
sub_key = CreateKey(key, "sub_key")
# Give the sub-key some named values
for value_name, value_data, value_type in test_data:
SetValueEx(sub_key, value_name, 0, value_type, value_data)
# Check we wrote as many items as we thought.
nkeys, nvalues, since_mod = QueryInfoKey(key)
assert nkeys==1, "Not the correct number of sub keys"
assert nvalues==1, "Not the correct number of values"
nkeys, nvalues, since_mod = QueryInfoKey(sub_key)
assert nkeys==0, "Not the correct number of sub keys"
assert nvalues==len(test_data), "Not the correct number of values"
# Close this key this way...
# (but before we do, copy the key as an integer - this allows
# us to test that the key really gets closed).
int_sub_key = int(sub_key)
CloseKey(sub_key)
try:
QueryInfoKey(int_sub_key)
raise RuntimeError, "It appears the CloseKey() function does not close the actual key!"
except EnvironmentError:
pass
# ... and close that key that way :-)
int_key = int(key)
key.Close()
try:
QueryInfoKey(int_key)
raise RuntimeError, "It appears the key.Close() function does not close the actual key!"
except EnvironmentError:
pass
def ReadTestData(root_key):
# Check we can get default value for this key.
val = QueryValue(root_key, test_key_name)
assert val=="Default value", "Registry didn't give back the correct value"
key = OpenKey(root_key, test_key_name)
# Read the sub-keys
sub_key = OpenKey(key, "sub_key")
# Check I can enumerate over the values.
index = 0
while 1:
try:
data = EnumValue(sub_key, index)
except EnvironmentError:
break
assert data in test_data, "Didn't read back the correct test data"
index = index + 1
assert index==len(test_data), "Didn't read the correct number of items"
# Check I can directly access each item
for value_name, value_data, value_type in test_data:
read_val, read_typ = QueryValueEx(sub_key, value_name)
assert read_val==value_data and read_typ == value_type, \
"Could not directly read the value"
sub_key.Close()
# Enumerate our main key.
read_val = EnumKey(key, 0)
assert read_val == "sub_key", "Read subkey value wrong"
try:
EnumKey(key, 1)
assert 0, "Was able to get a second key when I only have one!"
except EnvironmentError:
pass
key.Close()
def DeleteTestData(root_key):
key = OpenKey(root_key, test_key_name, 0, KEY_ALL_ACCESS)
sub_key = OpenKey(key, "sub_key", 0, KEY_ALL_ACCESS)
# It is not necessary to delete the values before deleting
# the key (although subkeys must not exist). We delete them
# manually just to prove we can :-)
for value_name, value_data, value_type in test_data:
DeleteValue(sub_key, value_name)
nkeys, nvalues, since_mod = QueryInfoKey(sub_key)
assert nkeys==0 and nvalues==0, "subkey not empty before delete"
sub_key.Close()
DeleteKey(key, "sub_key")
try:
# Shouldnt be able to delete it twice!
DeleteKey(key, "sub_key")
assert 0, "Deleting the key twice succeeded"
except EnvironmentError:
pass
key.Close()
DeleteKey(root_key, test_key_name)
# Opening should now fail!
try:
key = OpenKey(root_key, test_key_name)
assert 0, "Could open the non-existent key"
except WindowsError: # Use this error name this time
pass
def TestAll(root_key):
WriteTestData(root_key)
ReadTestData(root_key)
DeleteTestData(root_key)
# Test on my local machine.
TestAll(HKEY_CURRENT_USER)
print "Local registry tests worked"
try:
remote_name = sys.argv[sys.argv.index("--remote")+1]
except (IndexError, ValueError):
remote_name = None
if remote_name is not None:
try:
remote_key = ConnectRegistry(remote_name, HKEY_CURRENT_USER)
except EnvironmentError, exc:
print "Could not connect to the remote machine -", exc.strerror
remote_key = None
if remote_key is not None:
TestAll(remote_key)
print "Remote registry tests worked"
else:
print "Remote registry calls can be tested using",
print "'test_winreg.py --remote \\\\machine_name'"

View File

@ -17,6 +17,7 @@ class UserList:
return cmp(self.data, other.data) return cmp(self.data, other.data)
else: else:
return cmp(self.data, other) return cmp(self.data, other)
def __contains__(self, item): return item in self.data
def __len__(self): return len(self.data) def __len__(self): return len(self.data)
def __getitem__(self, i): return self.data[i] def __getitem__(self, i): return self.data[i]
def __setitem__(self, i, item): self.data[i] = item def __setitem__(self, i, item): self.data[i] = item

View File

@ -183,7 +183,7 @@ register("grail", Grail)
class WindowsDefault: class WindowsDefault:
def open(self, url, new=0): def open(self, url, new=0):
self.junk = os.popen("start " + url) os.startfile(url)
def open_new(self, url): def open_new(self, url):
self.open(url) self.open(url)