diff options
40 files changed, 1767 insertions, 886 deletions
diff --git a/Lib/dos-8x3/basehttp.py b/Lib/dos-8x3/basehttp.py index ea5095a..49f8984 100755 --- a/Lib/dos-8x3/basehttp.py +++ b/Lib/dos-8x3/basehttp.py @@ -93,19 +93,7 @@ class HTTPServer(SocketServer.TCPServer): """Override server_bind to store the server name.""" SocketServer.TCPServer.server_bind(self) host, port = self.socket.getsockname() - if not host or host == '0.0.0.0': - host = socket.gethostname() - try: - hostname, hostnames, hostaddrs = socket.gethostbyaddr(host) - except socket.error: - hostname = host - else: - if '.' not in hostname: - for host in hostnames: - if '.' in host: - hostname = host - break - self.server_name = hostname + self.server_name = socket.getfqdn(host) self.server_port = port @@ -418,16 +406,8 @@ class BaseHTTPRequestHandler(SocketServer.StreamRequestHandler): """ - (host, port) = self.client_address - try: - name, names, addresses = socket.gethostbyaddr(host) - except socket.error, msg: - return host - names.insert(0, name) - for name in names: - if '.' in name: return name - return names[0] - + host, port = self.client_address + return socket.getfqdn(host) # Essentially static class variables diff --git a/Lib/dos-8x3/cgihttps.py b/Lib/dos-8x3/cgihttps.py index fa30cbd..6a259a3 100755 --- a/Lib/dos-8x3/cgihttps.py +++ b/Lib/dos-8x3/cgihttps.py @@ -35,6 +35,10 @@ class CGIHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): """ + # Make rfile unbuffered -- we need to read one line and then pass + # the rest to a subprocess, so we can't use buffered input. + rbufsize = 0 + def do_POST(self): """Serve a POST request. diff --git a/Lib/dos-8x3/configpa.py b/Lib/dos-8x3/configpa.py index 38a85f4..e7636b9 100644 --- a/Lib/dos-8x3/configpa.py +++ b/Lib/dos-8x3/configpa.py @@ -36,6 +36,9 @@ ConfigParser -- responsible for for parsing a list of has_section(section) return whether the given section exists + has_option(section, option) + return whether the given option exists in the given section + options(section) return list of configuration options for the named section @@ -68,6 +71,18 @@ ConfigParser -- responsible for for parsing a list of getboolean(section, options) like get(), but convert value to a boolean (currently defined as 0 or 1, only) + + remove_section(section) + remove the given file section and all its options + + remove_option(section, option) + remove the given option from the given section + + set(section, option, value) + set the given option + + write(fp) + write the configuration state in .ini format """ import sys @@ -286,6 +301,64 @@ class ConfigParser: def optionxform(self, optionstr): return string.lower(optionstr) + def has_option(self, section, option): + """Check for the existence of a given option in a given section.""" + if not section or section == "DEFAULT": + return self.__defaults.has_key(option) + elif not self.has_section(section): + return 0 + else: + return self.__sections[section].has_key(option) + + def set(self, section, option, value): + """Set an option.""" + if not section or section == "DEFAULT": + sectdict = self.__defaults + else: + try: + sectdict = self.__sections[section] + except KeyError: + raise NoSectionError(section) + sectdict[option] = value + + def write(self, fp): + """Write an .ini-format representation of the configuration state.""" + if self.__defaults: + fp.write("[DEFAULT]\n") + for (key, value) in self.__defaults.items(): + fp.write("%s = %s\n" % (key, value)) + fp.write("\n") + for section in self.sections(): + fp.write("[" + section + "]\n") + sectdict = self.__sections[section] + for (key, value) in sectdict.items(): + if key == "__name__": + continue + fp.write("%s = %s\n" % (key, value)) + fp.write("\n") + + def remove_option(self, section, option): + """Remove an option.""" + if not section or section == "DEFAULT": + sectdict = self.__defaults + else: + try: + sectdict = self.__sections[section] + except KeyError: + raise NoSectionError(section) + existed = sectdict.has_key(key) + if existed: + del sectdict[key] + return existed + + def remove_section(self, section): + """Remove a file section.""" + if self.__sections.has_key(section): + del self.__sections[section] + return 1 + else: + return 0 + # # Regular expressions for parsing section headers and options. Note a # slight semantic change from the previous version, because of the use @@ -357,7 +430,6 @@ class ConfigParser: mo = self.OPTCRE.match(line) if mo: optname, vi, optval = mo.group('option', 'vi', 'value') - optname = string.lower(optname) if vi in ('=', ':') and ';' in optval: # ';' is a comment delimiter only if it follows # a spacing character diff --git a/Lib/dos-8x3/multifil.py b/Lib/dos-8x3/multifil.py index cc8f43c..e43d331 100755 --- a/Lib/dos-8x3/multifil.py +++ b/Lib/dos-8x3/multifil.py @@ -30,7 +30,8 @@ seekable stream object. import sys import string -Error = 'multifile.Error' +class Error(Exception): + pass class MultiFile: diff --git a/Lib/dos-8x3/posixfil.py b/Lib/dos-8x3/posixfil.py index 2db37e0..d358dc4 100755 --- a/Lib/dos-8x3/posixfil.py +++ b/Lib/dos-8x3/posixfil.py @@ -176,7 +176,7 @@ class _posixfile_: import sys, os if sys.platform in ('netbsd1', 'openbsd2', - 'freebsd2', 'freebsd3', + 'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5', 'bsdos2', 'bsdos3', 'bsdos4'): flock = struct.pack('lxxxxlxxxxlhh', \ l_start, l_len, os.getpid(), l_type, l_whence) @@ -192,7 +192,7 @@ class _posixfile_: if '?' in how: if sys.platform in ('netbsd1', 'openbsd2', - 'freebsd2', 'freebsd3', + 'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5', 'bsdos2', 'bsdos3', 'bsdos4'): l_start, l_len, l_pid, l_type, l_whence = \ struct.unpack('lxxxxlxxxxlhh', flock) diff --git a/Lib/dos-8x3/posixpat.py b/Lib/dos-8x3/posixpat.py index 14b9270..f7e0161 100755 --- a/Lib/dos-8x3/posixpat.py +++ b/Lib/dos-8x3/posixpat.py @@ -342,30 +342,25 @@ are left unchanged""" def normpath(path): """Normalize path, eliminating double slashes, etc.""" + if path == '': + return '.' import string - # Treat initial slashes specially - slashes = '' - while path[:1] == '/': - slashes = slashes + '/' - path = path[1:] - comps = string.splitfields(path, '/') - i = 0 - while i < len(comps): - if comps[i] == '.': - del comps[i] - while i < len(comps) and comps[i] == '': - del comps[i] - elif comps[i] == '..' and i > 0 and comps[i-1] not in ('', '..'): - del comps[i-1:i+1] - i = i-1 - elif comps[i] == '' and i > 0 and comps[i-1] <> '': - del comps[i] - else: - i = i+1 - # If the path is now empty, substitute '.' - if not comps and not slashes: - comps.append('.') - return slashes + string.joinfields(comps, '/') + initial_slash = (path[0] == '/') + comps = string.split(path, '/') + new_comps = [] + for comp in comps: + if comp in ('', '.'): + continue + if (comp != '..' or (not initial_slash and not new_comps) or + (new_comps and new_comps[-1] == '..')): + new_comps.append(comp) + elif new_comps: + new_comps.pop() + comps = new_comps + path = string.join(comps, '/') + if initial_slash: + path = '/' + path + return path or '.' def abspath(path): diff --git a/Lib/dos-8x3/simpleht.py b/Lib/dos-8x3/simpleht.py index 7125413..8a77758 100755 --- a/Lib/dos-8x3/simpleht.py +++ b/Lib/dos-8x3/simpleht.py @@ -15,6 +15,7 @@ import posixpath import BaseHTTPServer import urllib import cgi +import shutil from StringIO import StringIO @@ -151,12 +152,7 @@ class SimpleHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): to copy binary data as well. """ - - BLOCKSIZE = 8192 - while 1: - data = source.read(BLOCKSIZE) - if not data: break - outputfile.write(data) + shutil.copyfileobj(source, outputfile) def guess_type(self, path): """Guess the type of a file. diff --git a/Lib/dos-8x3/socketse.py b/Lib/dos-8x3/socketse.py index 5562fb0..a263f8e 100755 --- a/Lib/dos-8x3/socketse.py +++ b/Lib/dos-8x3/socketse.py @@ -412,10 +412,20 @@ class StreamRequestHandler(BaseRequestHandler): """Define self.rfile and self.wfile for stream sockets.""" + # Default buffer sizes for rfile, wfile. + # We default rfile to buffered because otherwise it could be + # really slow for large data (a getc() call per byte); we make + # wfile unbuffered because (a) often after a write() we want to + # read and we need to flush the line; (b) big writes to unbuffered + # files are typically optimized by stdio even when big reads + # aren't. + rbufsize = -1 + wbufsize = 0 + def setup(self): self.connection = self.request - self.rfile = self.connection.makefile('rb', 0) - self.wfile = self.connection.makefile('wb', 0) + self.rfile = self.connection.makefile('rb', self.rbufsize) + self.wfile = self.connection.makefile('wb', self.wbufsize) def finish(self): self.wfile.flush() diff --git a/Lib/dos-8x3/sre_comp.py b/Lib/dos-8x3/sre_comp.py index fa0cf37..97a57e2 100644 --- a/Lib/dos-8x3/sre_comp.py +++ b/Lib/dos-8x3/sre_comp.py @@ -5,22 +5,14 @@ # # Copyright (c) 1997-2000 by Secret Labs AB. All rights reserved. # -# Portions of this engine have been developed in cooperation with -# CNRI. Hewlett-Packard provided funding for 1.6 integration and -# other compatibility work. +# See the sre.py file for information on usage and redistribution. # -import array import _sre from sre_constants import * -# find an array type code that matches the engine's code size -for WORDSIZE in "BHil": - if len(array.array(WORDSIZE, [0]).tostring()) == _sre.getcodesize(): - break -else: - raise RuntimeError, "cannot find a usable array type" +MAXCODE = 65535 def _compile(code, pattern, flags): # internal: compile a (sub)pattern @@ -41,34 +33,16 @@ def _compile(code, pattern, flags): emit(OPCODES[op]) fixup = lambda x: x skip = len(code); emit(0) - for op, av in av: - emit(OPCODES[op]) - if op is NEGATE: - pass - elif op is LITERAL: - emit(fixup(av)) - elif op is RANGE: - emit(fixup(av[0])) - emit(fixup(av[1])) - elif op is CATEGORY: - if flags & SRE_FLAG_LOCALE: - emit(CHCODES[CH_LOCALE[av]]) - elif flags & SRE_FLAG_UNICODE: - emit(CHCODES[CH_UNICODE[av]]) - else: - emit(CHCODES[av]) - else: - raise error, "internal: unsupported set operator" - emit(OPCODES[FAILURE]) + _compile_charset(av, flags, code, fixup) code[skip] = len(code) - skip elif op is ANY: if flags & SRE_FLAG_DOTALL: - emit(OPCODES[op]) + emit(OPCODES[ANY_ALL]) else: - emit(OPCODES[CATEGORY]) - emit(CHCODES[CATEGORY_NOT_LINEBREAK]) + emit(OPCODES[ANY]) elif op in (REPEAT, MIN_REPEAT, MAX_REPEAT): if flags & SRE_FLAG_TEMPLATE: + raise error, "internal: unsupported template operator" emit(OPCODES[REPEAT]) skip = len(code); emit(0) emit(av[0]) @@ -76,40 +50,50 @@ def _compile(code, pattern, flags): _compile(code, av[2], flags) emit(OPCODES[SUCCESS]) code[skip] = len(code) - skip + elif _simple(av) and op == MAX_REPEAT: + emit(OPCODES[REPEAT_ONE]) + skip = len(code); emit(0) + emit(av[0]) + emit(av[1]) + _compile(code, av[2], flags) + emit(OPCODES[SUCCESS]) + code[skip] = len(code) - skip else: - lo, hi = av[2].getwidth() - if lo == 0: - raise error, "nothing to repeat" - if 0 and lo == hi == 1 and op is MAX_REPEAT: - # FIXME: <fl> need a better way to figure out when - # it's safe to use this one (in the parser, probably) - emit(OPCODES[MAX_REPEAT_ONE]) - skip = len(code); emit(0) - emit(av[0]) - emit(av[1]) - _compile(code, av[2], flags) - emit(OPCODES[SUCCESS]) - code[skip] = len(code) - skip + emit(OPCODES[REPEAT]) + skip = len(code); emit(0) + emit(av[0]) + emit(av[1]) + _compile(code, av[2], flags) + code[skip] = len(code) - skip + if op == MAX_REPEAT: + emit(OPCODES[MAX_UNTIL]) else: - emit(OPCODES[op]) - skip = len(code); emit(0) - emit(av[0]) - emit(av[1]) - _compile(code, av[2], flags) - emit(OPCODES[SUCCESS]) - code[skip] = len(code) - skip + emit(OPCODES[MIN_UNTIL]) elif op is SUBPATTERN: - group = av[0] - if group: + if av[0]: emit(OPCODES[MARK]) - emit((group-1)*2) + emit((av[0]-1)*2) + # _compile_info(code, av[1], flags) _compile(code, av[1], flags) - if group: + if av[0]: emit(OPCODES[MARK]) - emit((group-1)*2+1) + emit((av[0]-1)*2+1) elif op in (SUCCESS, FAILURE): emit(OPCODES[op]) - elif op in (ASSERT, ASSERT_NOT, CALL): + elif op in (ASSERT, ASSERT_NOT): + emit(OPCODES[op]) + skip = len(code); emit(0) + if av[0] >= 0: + emit(0) # look ahead + else: + lo, hi = av[1].getwidth() + if lo != hi: + raise error, "look-behind requires fixed-width pattern" + emit(lo) # look behind + _compile(code, av[1], flags) + emit(OPCODES[SUCCESS]) + code[skip] = len(code) - skip + elif op is CALL: emit(OPCODES[op]) skip = len(code); emit(0) _compile(code, av, flags) @@ -126,6 +110,7 @@ def _compile(code, pattern, flags): tail = [] for av in av[1]: skip = len(code); emit(0) + # _compile_info(code, av, flags) _compile(code, av, flags) emit(OPCODES[JUMP]) tail.append(len(code)); emit(0) @@ -141,51 +126,196 @@ def _compile(code, pattern, flags): emit(CHCODES[CH_UNICODE[av]]) else: emit(CHCODES[av]) - elif op is GROUP: + elif op is GROUPREF: if flags & SRE_FLAG_IGNORECASE: emit(OPCODES[OP_IGNORE[op]]) else: emit(OPCODES[op]) emit(av-1) - elif op is MARK: - emit(OPCODES[op]) - emit(av) else: raise ValueError, ("unsupported operand type", op) +def _compile_charset(charset, flags, code, fixup=None): + # compile charset subprogram + emit = code.append + if not fixup: + fixup = lambda x: x + for op, av in _optimize_charset(charset, fixup): + emit(OPCODES[op]) + if op is NEGATE: + pass + elif op is LITERAL: + emit(fixup(av)) + elif op is RANGE: + emit(fixup(av[0])) + emit(fixup(av[1])) + elif op is CHARSET: + code.extend(av) + elif op is CATEGORY: + if flags & SRE_FLAG_LOCALE: + emit(CHCODES[CH_LOCALE[av]]) + elif flags & SRE_FLAG_UNICODE: + emit(CHCODES[CH_UNICODE[av]]) + else: + emit(CHCODES[av]) + else: + raise error, "internal: unsupported set operator" + emit(OPCODES[FAILURE]) + +def _optimize_charset(charset, fixup): + # internal: optimize character set + out = [] + charmap = [0]*256 + try: + for op, av in charset: + if op is NEGATE: + out.append((op, av)) + elif op is LITERAL: + charmap[fixup(av)] = 1 + elif op is RANGE: + for i in range(fixup(av[0]), fixup(av[1])+1): + charmap[i] = 1 + elif op is CATEGORY: + # FIXME: could append to charmap tail + return charset # cannot compress + except IndexError: + # character set contains unicode characters + return charset + # compress character map + i = p = n = 0 + runs = [] + for c in charmap: + if c: + if n == 0: + p = i + n = n + 1 + elif n: + runs.append((p, n)) + n = 0 + i = i + 1 + if n: + runs.append((p, n)) + if len(runs) <= 2: + # use literal/range + for p, n in runs: + if n == 1: + out.append((LITERAL, p)) + else: + out.append((RANGE, (p, p+n-1))) + if len(out) < len(charset): + return out + else: + # use bitmap + data = [] + m = 1; v = 0 + for c in charmap: + if c: + v = v + m + m = m << 1 + if m > MAXCODE: + data.append(v) + m = 1; v = 0 + out.append((CHARSET, data)) + return out + return charset + +def _simple(av): + # check if av is a "simple" operator + lo, hi = av[2].getwidth() + if lo == 0: + raise error, "nothing to repeat" + return lo == hi == 1 and av[2][0][0] != SUBPATTERN + def _compile_info(code, pattern, flags): # internal: compile an info block. in the current version, - # this contains min/max pattern width and a literal prefix, - # if any + # this contains min/max pattern width, and an optional literal + # prefix or a character map lo, hi = pattern.getwidth() if lo == 0: return # not worth it # look for a literal prefix prefix = [] + prefix_skip = 0 + charset = [] # not used if not (flags & SRE_FLAG_IGNORECASE): + # look for literal prefix for op, av in pattern.data: if op is LITERAL: + if len(prefix) == prefix_skip: + prefix_skip = prefix_skip + 1 prefix.append(av) + elif op is SUBPATTERN and len(av[1]) == 1: + op, av = av[1][0] + if op is LITERAL: + prefix.append(av) + else: + break else: break + # if no prefix, look for charset prefix + if not prefix and pattern.data: + op, av = pattern.data[0] + if op is SUBPATTERN and av[1]: + op, av = av[1][0] + if op is LITERAL: + charset.append((op, av)) + elif op is BRANCH: + c = [] + for p in av[1]: + if not p: + break + op, av = p[0] + if op is LITERAL: + c.append((op, av)) + else: + break + else: + charset = c + elif op is BRANCH: + c = [] + for p in av[1]: + if not p: + break + op, av = p[0] + if op is LITERAL: + c.append((op, av)) + else: + break + else: + charset = c + elif op is IN: + charset = av +## if prefix: +## print "*** PREFIX", prefix, prefix_skip +## if charset: +## print "*** CHARSET", charset # add an info block emit = code.append emit(OPCODES[INFO]) skip = len(code); emit(0) # literal flag mask = 0 - if len(prefix) == len(pattern.data): - mask = 1 + if prefix: + mask = SRE_INFO_PREFIX + if len(prefix) == prefix_skip == len(pattern.data): + mask = mask + SRE_INFO_LITERAL + elif charset: + mask = mask + SRE_INFO_CHARSET emit(mask) # pattern length - emit(lo) - if hi < 32768: + if lo < MAXCODE: + emit(lo) + else: + emit(MAXCODE) + prefix = prefix[:MAXCODE] + if hi < MAXCODE: emit(hi) else: emit(0) # add literal prefix - emit(len(prefix)) if prefix: + emit(len(prefix)) # length + emit(prefix_skip) # skip code.extend(prefix) # generate overlap table table = [-1] + ([0]*len(prefix)) @@ -194,18 +324,18 @@ def _compile_info(code, pattern, flags): while table[i+1] > 0 and prefix[i] != prefix[table[i+1]-1]: table[i+1] = table[table[i+1]-1]+1 code.extend(table[1:]) # don't store first entry + elif charset: + _compile_charset(charset, 0, code) code[skip] = len(code) - skip -def compile(p, flags=0): - # internal: convert pattern list to internal format +STRING_TYPES = [type("")] - # compile, as necessary - if type(p) in (type(""), type(u"")): - import sre_parse - pattern = p - p = sre_parse.parse(p, flags) - else: - pattern = None +try: + STRING_TYPES.append(type(unicode(""))) +except NameError: + pass + +def _code(p, flags): flags = p.pattern.flags | flags code = [] @@ -218,12 +348,34 @@ def compile(p, flags=0): code.append(OPCODES[SUCCESS]) + return code + +def compile(p, flags=0): + # internal: convert pattern list to internal format + + if type(p) in STRING_TYPES: + import sre_parse + pattern = p + p = sre_parse.parse(p, flags) + else: + pattern = None + + code = _code(p, flags) + + # print code + # FIXME: <fl> get rid of this limitation! assert p.pattern.groups <= 100,\ "sorry, but this version only supports 100 named groups" + # map in either direction + groupindex = p.pattern.groupdict + indexgroup = [None] * p.pattern.groups + for k, i in groupindex.items(): + indexgroup[i] = k + return _sre.compile( - pattern, flags, - array.array(WORDSIZE, code).tostring(), - p.pattern.groups-1, p.pattern.groupdict + pattern, flags, code, + p.pattern.groups-1, + groupindex, indexgroup ) diff --git a/Lib/dos-8x3/sre_cons.py b/Lib/dos-8x3/sre_cons.py index 45f4f48..5a20930 100644 --- a/Lib/dos-8x3/sre_cons.py +++ b/Lib/dos-8x3/sre_cons.py @@ -6,9 +6,7 @@ # # Copyright (c) 1998-2000 by Secret Labs AB. All rights reserved. # -# Portions of this engine have been developed in cooperation with -# CNRI. Hewlett-Packard provided funding for 1.6 integration and -# other compatibility work. +# See the sre.py file for information on usage and redistribution. # # should this really be here? @@ -22,14 +20,16 @@ FAILURE = "failure" SUCCESS = "success" ANY = "any" +ANY_ALL = "any_all" ASSERT = "assert" ASSERT_NOT = "assert_not" AT = "at" BRANCH = "branch" CALL = "call" CATEGORY = "category" -GROUP = "group" -GROUP_IGNORE = "group_ignore" +CHARSET = "charset" +GROUPREF = "groupref" +GROUPREF_IGNORE = "groupref_ignore" IN = "in" IN_IGNORE = "in_ignore" INFO = "info" @@ -38,8 +38,9 @@ LITERAL = "literal" LITERAL_IGNORE = "literal_ignore" MARK = "mark" MAX_REPEAT = "max_repeat" -MAX_REPEAT_ONE = "max_repeat_one" +MAX_UNTIL = "max_until" MIN_REPEAT = "min_repeat" +MIN_UNTIL = "min_until" NEGATE = "negate" NOT_LITERAL = "not_literal" NOT_LITERAL_IGNORE = "not_literal_ignore" @@ -81,25 +82,27 @@ OPCODES = [ # failure=0 success=1 (just because it looks better that way :-) FAILURE, SUCCESS, - ANY, + ANY, ANY_ALL, ASSERT, ASSERT_NOT, AT, BRANCH, CALL, CATEGORY, - GROUP, GROUP_IGNORE, + CHARSET, + GROUPREF, GROUPREF_IGNORE, IN, IN_IGNORE, INFO, JUMP, LITERAL, LITERAL_IGNORE, MARK, - MAX_REPEAT, - MAX_REPEAT_ONE, - MIN_REPEAT, + MAX_UNTIL, + MIN_UNTIL, NOT_LITERAL, NOT_LITERAL_IGNORE, NEGATE, RANGE, - REPEAT + REPEAT, + REPEAT_ONE, + SUBPATTERN ] @@ -132,7 +135,7 @@ CHCODES = makedict(CHCODES) # replacement operations for "ignore case" mode OP_IGNORE = { - GROUP: GROUP_IGNORE, + GROUPREF: GROUPREF_IGNORE, IN: IN_IGNORE, LITERAL: LITERAL_IGNORE, NOT_LITERAL: NOT_LITERAL_IGNORE @@ -166,13 +169,18 @@ CH_UNICODE = { } # flags -SRE_FLAG_TEMPLATE = 1 -SRE_FLAG_IGNORECASE = 2 -SRE_FLAG_LOCALE = 4 -SRE_FLAG_MULTILINE = 8 -SRE_FLAG_DOTALL = 16 -SRE_FLAG_UNICODE = 32 -SRE_FLAG_VERBOSE = 64 +SRE_FLAG_TEMPLATE = 1 # template mode (disable backtracking) +SRE_FLAG_IGNORECASE = 2 # case insensitive +SRE_FLAG_LOCALE = 4 # honour system locale +SRE_FLAG_MULTILINE = 8 # treat target as multiline string +SRE_FLAG_DOTALL = 16 # treat target as a single string +SRE_FLAG_UNICODE = 32 # use unicode locale +SRE_FLAG_VERBOSE = 64 # ignore whitespace and comments + +# flags for INFO primitive +SRE_INFO_PREFIX = 1 # has prefix +SRE_INFO_LITERAL = 2 # entire pattern is literal (given by prefix) +SRE_INFO_CHARSET = 4 # pattern starts with character from given set if __name__ == "__main__": import string @@ -201,6 +209,7 @@ if __name__ == "__main__": dump(f, OPCODES, "SRE_OP") dump(f, ATCODES, "SRE") dump(f, CHCODES, "SRE") + f.write("#define SRE_FLAG_TEMPLATE %d\n" % SRE_FLAG_TEMPLATE) f.write("#define SRE_FLAG_IGNORECASE %d\n" % SRE_FLAG_IGNORECASE) f.write("#define SRE_FLAG_LOCALE %d\n" % SRE_FLAG_LOCALE) @@ -208,5 +217,10 @@ if __name__ == "__main__": f.write("#define SRE_FLAG_DOTALL %d\n" % SRE_FLAG_DOTALL) f.write("#define SRE_FLAG_UNICODE %d\n" % SRE_FLAG_UNICODE) f.write("#define SRE_FLAG_VERBOSE %d\n" % SRE_FLAG_VERBOSE) + + f.write("#define SRE_INFO_PREFIX %d\n" % SRE_INFO_PREFIX) + f.write("#define SRE_INFO_LITERAL %d\n" % SRE_INFO_LITERAL) + f.write("#define SRE_INFO_CHARSET %d\n" % SRE_INFO_CHARSET) + f.close() print "done" diff --git a/Lib/dos-8x3/sre_pars.py b/Lib/dos-8x3/sre_pars.py index 53616f6..a50191e 100644 --- a/Lib/dos-8x3/sre_pars.py +++ b/Lib/dos-8x3/sre_pars.py @@ -5,33 +5,24 @@ # # Copyright (c) 1998-2000 by Secret Labs AB. All rights reserved. # -# Portions of this engine have been developed in cooperation with -# CNRI. Hewlett-Packard provided funding for 1.6 integration and -# other compatibility work. +# See the sre.py file for information on usage and redistribution. # import string, sys -import _sre - from sre_constants import * -# FIXME: should be 65535, but the arraymodule is still broken -MAXREPEAT = 32767 - -# FIXME: might change in 2.0 final. but for now, this seems -# to be the best way to be compatible with 1.5.2 -CHARMASK = 0xff +MAXREPEAT = 65535 SPECIAL_CHARS = ".\\[{()*+?^$|" REPEAT_CHARS = "*+?{" -DIGITS = tuple(string.digits) +DIGITS = tuple("012345689") OCTDIGITS = tuple("01234567") HEXDIGITS = tuple("0123456789abcdefABCDEF") -WHITESPACE = tuple(string.whitespace) +WHITESPACE = tuple(" \t\n\r\v\f") ESCAPES = { r"\a": (LITERAL, 7), @@ -69,7 +60,8 @@ FLAGS = { "u": SRE_FLAG_UNICODE, } -class State: +class Pattern: + # master pattern object. keeps track of global attributes def __init__(self): self.flags = 0 self.groups = 1 @@ -89,6 +81,33 @@ class SubPattern: data = [] self.data = data self.width = None + def dump(self, level=0): + nl = 1 + for op, av in self.data: + print level*" " + op,; nl = 0 + if op == "in": + # member sublanguage + print; nl = 1 + for op, a in av: + print (level+1)*" " + op, a + elif op == "branch": + print; nl = 1 + i = 0 + for a in av[1]: + if i > 0: + print level*" " + "or" + a.dump(level+1); nl = 1 + i = i + 1 + elif type(av) in (type(()), type([])): + for a in av: + if isinstance(a, SubPattern): + if not nl: print + a.dump(level+1); nl = 1 + else: + print a, ; nl = 0 + else: + print av, ; nl = 0 + if not nl: print def __repr__(self): return repr(self.data) def __len__(self): @@ -112,12 +131,12 @@ class SubPattern: lo = hi = 0L for op, av in self.data: if op is BRANCH: - l = sys.maxint - h = 0 + i = sys.maxint + j = 0 for av in av[1]: - i, j = av.getwidth() - l = min(l, i) - h = min(h, j) + l, h = av.getwidth() + i = min(i, l) + j = max(j, h) lo = lo + i hi = hi + j elif op is CALL: @@ -142,12 +161,13 @@ class SubPattern: class Tokenizer: def __init__(self, string): - self.index = 0 self.string = string - self.next = self.__next() + self.index = 0 + self.__next() def __next(self): if self.index >= len(self.string): - return None + self.next = None + return char = self.string[self.index] if char[0] == "\\": try: @@ -156,21 +176,21 @@ class Tokenizer: raise error, "bogus escape" char = char + c self.index = self.index + len(char) - return char - def match(self, char): + self.next = char + def match(self, char, skip=1): if char == self.next: - self.next = self.__next() - return 1 - return 0 - def match_set(self, set): - if self.next and self.next in set: - self.next = self.__next() + if skip: + self.__next() return 1 return 0 def get(self): this = self.next - self.next = self.__next() + self.__next() return this + def tell(self): + return self.index, self.next + def seek(self, index): + self.index, self.next = index def isident(char): return "a" <= char <= "z" or "A" <= char <= "Z" or char == "_" @@ -207,15 +227,19 @@ def _class_escape(source, escape): return code try: if escape[1:2] == "x": - while source.next in HEXDIGITS: + # hexadecimal escape (exactly two digits) + while source.next in HEXDIGITS and len(escape) < 4: escape = escape + source.get() escape = escape[2:] - return LITERAL, int(escape[-4:], 16) & CHARMASK + if len(escape) != 2: + raise error, "bogus escape: %s" % repr("\\" + escape) + return LITERAL, int(escape, 16) & 0xff elif str(escape[1:2]) in OCTDIGITS: - while source.next in OCTDIGITS: + # octal escape (up to three digits) + while source.next in OCTDIGITS and len(escape) < 5: escape = escape + source.get() escape = escape[1:] - return LITERAL, int(escape[-6:], 8) & CHARMASK + return LITERAL, int(escape, 8) & 0xff if len(escape) == 2: return LITERAL, ord(escape[1]) except ValueError: @@ -232,34 +256,57 @@ def _escape(source, escape, state): return code try: if escape[1:2] == "x": - while source.next in HEXDIGITS: + # hexadecimal escape + while source.next in HEXDIGITS and len(escape) < 4: escape = escape + source.get() escape = escape[2:] - return LITERAL, int(escape[-4:], 16) & CHARMASK + if len(escape) != 2: + raise error, "bogus escape: %s" % repr("\\" + escape) + return LITERAL, int(escape, 16) & 0xff + elif escape[1:2] == "0": + # octal escape + while source.next in OCTDIGITS and len(escape) < 5: + escape = escape + source.get() + return LITERAL, int(escape[1:], 8) & 0xff elif escape[1:2] in DIGITS: - while 1: - group = _group(escape, state.groups) - if group: - if (not source.next or - not _group(escape + source.next, state.groups)): - return GROUP, group - escape = escape + source.get() - elif source.next in OCTDIGITS: + # octal escape *or* decimal group reference (sigh) + here = source.tell() + if source.next in DIGITS: + escape = escape + source.get() + if escape[2] in OCTDIGITS and source.next in OCTDIGITS: + # got three octal digits; this is an octal escape escape = escape + source.get() - else: - break - escape = escape[1:] - return LITERAL, int(escape[-6:], 8) & CHARMASK + return LITERAL, int(escape[1:], 8) & 0xff + # got at least one decimal digit; this is a group reference + group = _group(escape, state.groups) + if group: + return GROUPREF, group + raise error, "bogus escape: %s" % repr(escape) if len(escape) == 2: return LITERAL, ord(escape[1]) except ValueError: pass raise error, "bogus escape: %s" % repr(escape) -def _branch(pattern, items): - # form a branch operator from a set of items +def _parse_sub(source, state, nested=1): + # parse an alternation: a|b|c + + items = [] + while 1: + items.append(_parse(source, state)) + if source.match("|"): + continue + if not nested: + break + if not source.next or source.match(")", 0): + break + else: + raise error, "pattern not properly closed" - subpattern = SubPattern(pattern) + if len(items) == 1: + return items[0] + + subpattern = SubPattern(state) # check if all items share a common prefix while 1: @@ -286,7 +333,7 @@ def _branch(pattern, items): break else: # we can store this as a character set instead of a - # branch (FIXME: use a range if possible) + # branch (the compiler may optimize this even more) set = [] for item in items: set.append(item[0]) @@ -297,8 +344,7 @@ def _branch(pattern, items): return subpattern def _parse(source, state): - - # parse regular expression pattern into an operator list. + # parse a simple pattern subpattern = SubPattern(state) @@ -357,7 +403,11 @@ def _parse(source, state): code2 = LITERAL, ord(this) if code1[0] != LITERAL or code2[0] != LITERAL: raise error, "illegal range" - set.append((RANGE, (code1[1], code2[1]))) + lo = code1[1] + hi = code2[1] + if hi < lo: + raise error, "illegal range" + set.append((RANGE, (lo, hi))) else: if code1[0] is IN: code1 = code1[1][0] @@ -381,6 +431,7 @@ def _parse(source, state): elif this == "+": min, max = 1, MAXREPEAT elif this == "{": + here = source.tell() min, max = 0, MAXREPEAT lo = hi = "" while source.next in DIGITS: @@ -391,7 +442,9 @@ def _parse(source, state): else: hi = lo if not source.match("}"): - raise error, "bogus range" + subpattern.append((LITERAL, ord(this))) + source.seek(here) + continue if lo: min = int(lo) if hi: @@ -448,7 +501,8 @@ def _parse(source, state): gid = state.groupdict.get(name) if gid is None: raise error, "unknown group name" - subpattern.append((GROUP, gid)) + subpattern.append((GROUPREF, gid)) + continue else: char = source.get() if char is None: @@ -463,49 +517,41 @@ def _parse(source, state): if source.next is None or source.next == ")": break source.get() - elif source.next in ("=", "!"): + if not source.match(")"): + raise error, "unbalanced parenthesis" + continue + elif source.next in ("=", "!", "<"): # lookahead assertions char = source.get() - b = [] - while 1: - p = _parse(source, state) - if source.next == ")": - if b: - b.append(p) - p = _branch(state, b) - if char == "=": - subpattern.append((ASSERT, p)) - else: - subpattern.append((ASSERT_NOT, p)) - break - elif source.match("|"): - b.append(p) - else: - raise error, "pattern not properly closed" + dir = 1 + if char == "<": + if source.next not in ("=", "!"): + raise error, "syntax error" + dir = -1 # lookbehind + char = source.get() + p = _parse_sub(source, state) + if not source.match(")"): + raise error, "unbalanced parenthesis" + if char == "=": + subpattern.append((ASSERT, (dir, p))) + else: + subpattern.append((ASSERT_NOT, (dir, p))) + continue else: # flags while FLAGS.has_key(source.next): state.flags = state.flags | FLAGS[source.get()] if group: # parse group contents - b = [] if group == 2: # anonymous group group = None else: group = state.getgroup(name) - while 1: - p = _parse(source, state) - if source.match(")"): - if b: - b.append(p) - p = _branch(state, b) - subpattern.append((SUBPATTERN, (group, p))) - break - elif source.match("|"): - b.append(p) - else: - raise error, "group not properly closed" + p = _parse_sub(source, state) + if not source.match(")"): + raise error, "unbalanced parenthesis" + subpattern.append((SUBPATTERN, (group, p))) else: while 1: char = source.get() @@ -528,26 +574,25 @@ def _parse(source, state): return subpattern -def parse(pattern, flags=0): +def parse(str, flags=0, pattern=None): # parse 're' pattern into list of (opcode, argument) tuples - source = Tokenizer(pattern) - state = State() - state.flags = flags - b = [] - while 1: - p = _parse(source, state) - tail = source.get() - if tail == "|": - b.append(p) - elif tail == ")": - raise error, "unbalanced parenthesis" - elif tail is None: - if b: - b.append(p) - p = _branch(state, b) - break - else: - raise error, "bogus characters at end of regular expression" + + source = Tokenizer(str) + + if pattern is None: + pattern = Pattern() + pattern.flags = flags + + p = _parse_sub(source, pattern, 0) + + tail = source.get() + if tail == ")": + raise error, "unbalanced parenthesis" + elif tail: + raise error, "bogus characters at end of regular expression" + + # p.dump() + return p def parse_template(source, pattern): @@ -599,7 +644,7 @@ def parse_template(source, pattern): break if not code: this = this[1:] - code = LITERAL, int(this[-6:], 8) & CHARMASK + code = LITERAL, int(this[-6:], 8) & 0xff a(code) else: try: @@ -629,4 +674,4 @@ def expand_template(template, match): if s is None: raise error, "empty group" a(s) - return sep.join(p) + return string.join(p, sep) diff --git a/Lib/dos-8x3/test_arr.py b/Lib/dos-8x3/test_arr.py index a82ace5..d3fe7e9 100644 --- a/Lib/dos-8x3/test_arr.py +++ b/Lib/dos-8x3/test_arr.py @@ -105,6 +105,26 @@ def testtype(type, example): a[1:-1] = a if a != array.array(type, "aabcdee"): raise TestFailed, "array(%s) self-slice-assign (cntr)" % `type` + if a.index("e") != 5: + raise TestFailed, "array(%s) index-test" % `type` + if a.count("a") != 2: + raise TestFailed, "array(%s) count-test" % `type` + a.remove("e") + if a != array.array(type, "aabcde"): + raise TestFailed, "array(%s) remove-test" % `type` + if a.pop(0) != "a": + raise TestFailed, "array(%s) pop-test" % `type` + if a.pop(1) != "b": + raise TestFailed, "array(%s) pop-test" % `type` + a.extend(array.array(type, "xyz")) + if a != array.array(type, "acdexyz"): + raise TestFailed, "array(%s) extend-test" % `type` + a.pop() + a.pop() + a.pop() + a.pop() + if a != array.array(type, "acd"): + raise TestFailed, "array(%s) pop-test" % `type` else: a = array.array(type, [1, 2, 3, 4, 5]) a[:-1] = a @@ -118,6 +138,26 @@ def testtype(type, example): a[1:-1] = a if a != array.array(type, [1, 1, 2, 3, 4, 5, 5]): raise TestFailed, "array(%s) self-slice-assign (cntr)" % `type` + if a.index(5) != 5: + raise TestFailed, "array(%s) index-test" % `type` + if a.count(1) != 2: + raise TestFailed, "array(%s) count-test" % `type` + a.remove(5) + if a != array.array(type, [1, 1, 2, 3, 4, 5]): + raise TestFailed, "array(%s) remove-test" % `type` + if a.pop(0) != 1: + raise TestFailed, "array(%s) pop-test" % `type` + if a.pop(1) != 2: + raise TestFailed, "array(%s) pop-test" % `type` + a.extend(array.array(type, [7, 8, 9])) + if a != array.array(type, [1, 3, 4, 5, 7, 8, 9]): + raise TestFailed, "array(%s) extend-test" % `type` + a.pop() + a.pop() + a.pop() + a.pop() + if a != array.array(type, [1, 3, 4]): + raise TestFailed, "array(%s) pop-test" % `type` # test that overflow exceptions are raised as expected for assignment # to array of specific integral types diff --git a/Lib/dos-8x3/test_bin.py b/Lib/dos-8x3/test_bin.py index 534fa73..52f817b 100644 --- a/Lib/dos-8x3/test_bin.py +++ b/Lib/dos-8x3/test_bin.py @@ -1,46 +1,112 @@ -#! /usr/bin/env python -"""Test script for the binhex C module - - Uses the mechanism of the python binhex module - Roger E. Masse -""" -import binhex -import tempfile +"""Test the binascii C module.""" + from test_support import verbose +import binascii + +# Show module doc string +print binascii.__doc__ + +# Show module exceptions +print binascii.Error +print binascii.Incomplete + +# Check presence and display doc strings of all functions +funcs = [] +for suffix in "base64", "hqx", "uu": + prefixes = ["a2b_", "b2a_"] + if suffix == "hqx": + prefixes.extend(["crc_", "rlecode_", "rledecode_"]) + for prefix in prefixes: + name = prefix + suffix + funcs.append(getattr(binascii, name)) +for func in funcs: + print "%-15s: %s" % (func.__name__, func.__doc__) + +# Create binary test data +testdata = "The quick brown fox jumps over the lazy dog.\r\n" +for i in range(256): + # Be slow so we don't depend on other modules + testdata = testdata + chr(i) +testdata = testdata + "\r\nHello world.\n" + +# Test base64 with valid data +print "base64 test" +MAX_BASE64 = 57 +lines = [] +for i in range(0, len(testdata), MAX_BASE64): + b = testdata[i:i+MAX_BASE64] + a = binascii.b2a_base64(b) + lines.append(a) + print a, +res = "" +for line in lines: + b = binascii.a2b_base64(line) + res = res + b +assert res == testdata + +# Test base64 with random invalid characters sprinkled throughout +# (This requires a new version of binascii.) +fillers = "" +valid = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/" +for i in range(256): + c = chr(i) + if c not in valid: + fillers = fillers + c +def addnoise(line): + noise = fillers + ratio = len(line) / len(noise) + res = "" + while line and noise: + if len(line) / len(noise) > ratio: + c, line = line[0], line[1:] + else: + c, noise = noise[0], noise[1:] + res = res + c + return res + noise + line +res = "" +for line in map(addnoise, lines): + b = binascii.a2b_base64(line) + res = res + b +assert res == testdata + +# Test uu +print "uu test" +MAX_UU = 45 +lines = [] +for i in range(0, len(testdata), MAX_UU): + b = testdata[i:i+MAX_UU] + a = binascii.b2a_uu(b) + lines.append(a) + print a, +res = "" +for line in lines: + b = binascii.a2b_uu(line) + res = res + b +assert res == testdata + +# Test crc32() +crc = binascii.crc32("Test the CRC-32 of") +crc = binascii.crc32(" this string.", crc) +if crc != 1571220330: + print "binascii.crc32() failed." + +# The hqx test is in test_binhex.py -def test(): - - try: - fname1 = tempfile.mktemp() - fname2 = tempfile.mktemp() - f = open(fname1, 'w') - except: - raise ImportError, "Cannot test binhex without a temp file" - - start = 'Jack is my hero' - f.write(start) - f.close() - - binhex.binhex(fname1, fname2) - if verbose: - print 'binhex' - - binhex.hexbin(fname2, fname1) - if verbose: - print 'hexbin' - - f = open(fname1, 'r') - finish = f.readline() - - if start <> finish: - print 'Error: binhex <> hexbin' - elif verbose: - print 'binhex == hexbin' - - try: - import os - os.unlink(fname1) - os.unlink(fname2) - except: - pass -test() +# test hexlification +s = '{s\005\000\000\000worldi\002\000\000\000s\005\000\000\000helloi\001\000\000\0000' +t = binascii.b2a_hex(s) +u = binascii.a2b_hex(t) +if s <> u: + print 'binascii hexlification failed' +try: + binascii.a2b_hex(t[:-1]) +except TypeError: + pass +else: + print 'expected TypeError not raised' +try: + binascii.a2b_hex(t[:-1] + 'q') +except TypeError: + pass +else: + print 'expected TypeError not raised' diff --git a/Lib/dos-8x3/test_exc.py b/Lib/dos-8x3/test_exc.py index 7bc515c..7ee203c 100755 --- a/Lib/dos-8x3/test_exc.py +++ b/Lib/dos-8x3/test_exc.py @@ -19,7 +19,7 @@ def test_raise_catch(exc): def r(thing): test_raise_catch(thing) - if type(thing) == ClassType: + if isinstance(thing, ClassType): print thing.__name__ else: print thing @@ -86,6 +86,14 @@ r(SyntaxError) try: exec '/\n' except SyntaxError: pass +r(IndentationError) + +r(TabError) +# can only be tested under -tt, and is the only test for -tt +#try: compile("try:\n\t1/0\n \t1/0\nfinally:\n pass\n", '<string>', 'exec') +#except TabError: pass +#else: raise TestFailed + r(SystemError) print '(hard to reproduce)' diff --git a/Lib/dos-8x3/test_ext.py b/Lib/dos-8x3/test_ext.py index 6cca199..de2312b 100644 --- a/Lib/dos-8x3/test_ext.py +++ b/Lib/dos-8x3/test_ext.py @@ -85,10 +85,13 @@ assert d == d2, "function call modified dictionary" # what about willful misconduct? def saboteur(**kw): - kw['x'] = locals() + kw['x'] = locals() # yields a cyclic kw + return kw d = {} -saboteur(a=1, **d) +kw = saboteur(a=1, **d) assert d == {} +# break the cycle +del kw['x'] try: g(1, 2, 3, **{'x':4, 'y':5}) diff --git a/Lib/dos-8x3/test_fcn.py b/Lib/dos-8x3/test_fcn.py index b59efda..3c1be88 100644 --- a/Lib/dos-8x3/test_fcn.py +++ b/Lib/dos-8x3/test_fcn.py @@ -17,7 +17,7 @@ if verbose: print 'Status from fnctl with O_NONBLOCK: ', rv if sys.platform in ('netbsd1', - 'freebsd2', 'freebsd3', + 'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5', 'bsdos2', 'bsdos3', 'bsdos4', 'openbsd', 'openbsd2'): lockdata = struct.pack('lxxxxlxxxxlhh', 0, 0, 0, FCNTL.F_WRLCK, 0) diff --git a/Lib/dos-8x3/test_for.py b/Lib/dos-8x3/test_for.py index 67e30df..4fd2662 100644 --- a/Lib/dos-8x3/test_for.py +++ b/Lib/dos-8x3/test_for.py @@ -6,14 +6,24 @@ child after a fork(). On some systems (e.g. Solaris without posix threads) we find that all active threads survive in the child after a fork(); this is an error. +On BeOS, you CANNOT mix threads and fork(), the behaviour is undefined. +That's OK, fork() is a grotesque hack anyway. ;-) [cjh] + """ import os, sys, time, thread +from test_support import TestSkipped + +try: + if os.uname()[0] == "BeOS": + raise TestSkipped, "can't mix os.fork with threads on BeOS" +except AttributeError: + pass try: os.fork except AttributeError: - raise ImportError, "os.fork not defined -- skipping test_fork1" + raise TestSkipped, "os.fork not defined -- skipping test_fork1" LONGSLEEP = 2 diff --git a/Lib/dos-8x3/test_gra.py b/Lib/dos-8x3/test_gra.py index fa09e8c..ef7c09b 100755 --- a/Lib/dos-8x3/test_gra.py +++ b/Lib/dos-8x3/test_gra.py @@ -260,6 +260,50 @@ print print 0 or 1, 0 or 1, print 0 or 1 +print 'extended print_stmt' # 'print' '>>' test ',' +import sys +print >> sys.stdout, 1, 2, 3 +print >> sys.stdout, 1, 2, 3, +print >> sys.stdout +print >> sys.stdout, 0 or 1, 0 or 1, +print >> sys.stdout, 0 or 1 + +# test print >> None +class Gulp: + def write(self, msg): pass + +def driver(): + oldstdout = sys.stdout + sys.stdout = Gulp() + try: + tellme(Gulp()) + tellme() + finally: + sys.stdout = oldstdout + +# we should see this once +def tellme(file=sys.stdout): + print >> file, 'hello world' + +driver() + +# we should not see this at all +def tellme(file=None): + print >> file, 'goodbye universe' + +driver() + +# syntax errors +def check_syntax(statement): + try: + compile(statement, '<string>', 'exec') + except SyntaxError: + pass + else: + print 'Missing SyntaxError: "%s"' % statement +check_syntax('print ,') +check_syntax('print >> x,') + print 'del_stmt' # 'del' exprlist del abc del x, y, (z, xyz) @@ -542,3 +586,49 @@ class C: def meth1(self): pass def meth2(self, arg): pass def meth3(self, a1, a2): pass + +# list comprehension tests +nums = [1, 2, 3, 4, 5] +strs = ["Apple", "Banana", "Coconut"] +spcs = [" Apple", " Banana ", "Coco nut "] + +print [s.strip() for s in spcs] +print [3 * x for x in nums] +print [x for x in nums if x > 2] +print [(i, s) for i in nums for s in strs] +print [(i, s) for i in nums for s in [f for f in strs if "n" in f]] +try: + eval("[i, s for i in nums for s in strs]") + print "FAIL: should have raised a SyntaxError!" +except SyntaxError: + print "good: got a SyntaxError as expected" + +try: + eval("[x if y]") + print "FAIL: should have raised a SyntaxError!" +except SyntaxError: + print "good: got a SyntaxError as expected" + +suppliers = [ + (1, "Boeing"), + (2, "Ford"), + (3, "Macdonalds") +] + +parts = [ + (10, "Airliner"), + (20, "Engine"), + (30, "Cheeseburger") +] + +suppart = [ + (1, 10), (1, 20), (2, 20), (3, 30) +] + +print [ + (sname, pname) + for (sno, sname) in suppliers + for (pno, pname) in parts + for (sp_sno, sp_pno) in suppart + if sno == sp_sno and pno == sp_pno +] diff --git a/Lib/dos-8x3/test_gzi.py b/Lib/dos-8x3/test_gzi.py index 3ea2ba9..2366d02 100644 --- a/Lib/dos-8x3/test_gzi.py +++ b/Lib/dos-8x3/test_gzi.py @@ -16,15 +16,39 @@ data2 = """/* zlibmodule.c -- gzip-compatible data compression */ /* See http://www.winimage.com/zLibDll for Windows */ """ -f = gzip.GzipFile(filename, 'wb') ; f.write(data1) ; f.close() +f = gzip.GzipFile(filename, 'wb') ; f.write(data1 * 50) ; f.close() f = gzip.GzipFile(filename, 'rb') ; d = f.read() ; f.close() -assert d == data1 +assert d == data1*50 # Append to the previous file -f = gzip.GzipFile(filename, 'ab') ; f.write(data2) ; f.close() +f = gzip.GzipFile(filename, 'ab') ; f.write(data2 * 15) ; f.close() f = gzip.GzipFile(filename, 'rb') ; d = f.read() ; f.close() -assert d == data1+data2 +assert d == (data1*50) + (data2*15) + +# Try .readline() with varying line lengths + +f = gzip.GzipFile(filename, 'rb') +line_length = 0 +while 1: + L = f.readline( line_length ) + if L == "" and line_length != 0: break + assert len(L) <= line_length + line_length = (line_length + 1) % 50 +f.close() + +# Try .readlines() + +f = gzip.GzipFile(filename, 'rb') +L = f.readlines() +f.close() + +f = gzip.GzipFile(filename, 'rb') +while 1: + L = f.readlines(150) + if L == []: break +f.close() + os.unlink( filename ) diff --git a/Lib/dos-8x3/test_lin.py b/Lib/dos-8x3/test_lin.py index 4b612a7..4faaab1 100644 --- a/Lib/dos-8x3/test_lin.py +++ b/Lib/dos-8x3/test_lin.py @@ -1,5 +1,6 @@ -from test_support import verbose, findfile, TestFailed +from test_support import verbose, findfile, TestFailed, TestSkipped import linuxaudiodev +import errno import os def play_sound_file(path): @@ -9,6 +10,8 @@ def play_sound_file(path): try: a = linuxaudiodev.open('w') except linuxaudiodev.error, msg: + if msg[0] in (errno.EACCES, errno.ENODEV): + raise TestSkipped, msg raise TestFailed, msg else: a.write(data) diff --git a/Lib/dos-8x3/test_mat.py b/Lib/dos-8x3/test_mat.py index 5c8efc6..6d6bc44 100644 --- a/Lib/dos-8x3/test_mat.py +++ b/Lib/dos-8x3/test_mat.py @@ -129,18 +129,6 @@ testit('pow(1,0)', math.pow(1,0), 1) testit('pow(2,1)', math.pow(2,1), 2) testit('pow(2,-1)', math.pow(2,-1), 0.5) -print 'rint' -try: - math.rint -except AttributeError: - # this platform does not have rint, that is fine, skip the test - pass -else: - testit('rint(0.7)', math.rint(0.7), 1) - testit('rint(-0.3)', math.rint(-0.3), 0) - testit('rint(2.5)', math.rint(2.5), 2) - testit('rint(3.5)', math.rint(3.5), 4) - print 'sin' testit('sin(0)', math.sin(0), 0) testit('sin(pi/2)', math.sin(math.pi/2), 1) diff --git a/Lib/dos-8x3/test_mma.py b/Lib/dos-8x3/test_mma.py index c3cafca..73c1a15 100644 --- a/Lib/dos-8x3/test_mma.py +++ b/Lib/dos-8x3/test_mma.py @@ -69,7 +69,7 @@ def test_both(): m.seek(0,2) print ' Seek to last byte' assert m.tell() == len(m) - + print ' Try to seek to negative position...' try: m.seek(-1) @@ -94,6 +94,26 @@ def test_both(): else: assert 0, 'expected a ValueError but did not get it' + # Try resizing map + print ' Attempting resize()' + try: + m.resize( 512 ) + except SystemError: + # resize() not supported + # No messages are printed, since the output of this test suite + # would then be different across platforms. + pass + else: + # resize() is supported + assert len(m) == 512, "len(m) is %d, but expecting 512" % (len(m),) + # Check that we can no longer seek beyond the new size. + try: + m.seek(513,0) + except ValueError: + pass + else: + assert 0, 'Could seek beyond the new size' + m.close() os.unlink("foo") print ' Test passed' diff --git a/Lib/dos-8x3/test_ntp.py b/Lib/dos-8x3/test_ntp.py index 1f824a5..11f2f44 100644 --- a/Lib/dos-8x3/test_ntp.py +++ b/Lib/dos-8x3/test_ntp.py @@ -1,5 +1,6 @@ import ntpath import string +import os errors = 0 @@ -34,6 +35,15 @@ tester('ntpath.isabs("\\\\conky\\mountpoint\\")', 1) tester('ntpath.isabs("\\foo")', 1) tester('ntpath.isabs("\\foo\\bar")', 1) +tester('ntpath.abspath("C:\\")', "C:\\") + +tester('ntpath.commonprefix(["/home/swenson/spam", "/home/swen/spam"])', + "/home/swen") +tester('ntpath.commonprefix(["\\home\\swen\\spam", "\\home\\swen\\eggs"])', + "\\home\\swen\\") +tester('ntpath.commonprefix(["/home/swen/spam", "/home/swen/spam"])', + "/home/swen/spam") + if errors: print str(errors) + " errors." else: diff --git a/Lib/dos-8x3/test_ope.py b/Lib/dos-8x3/test_ope.py index 8d3864c..723e57c 100755 --- a/Lib/dos-8x3/test_ope.py +++ b/Lib/dos-8x3/test_ope.py @@ -1,77 +1,22 @@ -import operator -import sys +# Test to see if openpty works. (But don't worry if it isn't available.) -def test(name, input, output, *args): - print 'testing:', name - f = getattr(operator, name) - params = (input,) + args - try: - val = apply(f, params) - except: - val = sys.exc_type - if val <> output: - print '%s%s = %s: %s expected' % (f.__name__, params, `val`, `output`) +import os +from test_support import verbose, TestFailed, TestSkipped -test('abs', -1, 1) -test('add', 3, 7, 4) -test('and_', 0xf, 0xa, 0xa) -test('concat', 'py', 'python', 'thon') +try: + if verbose: + print "Calling os.openpty()" + master, slave = os.openpty() + if verbose: + print "(master, slave) = (%d, %d)"%(master, slave) +except AttributeError: + raise TestSkipped, "No openpty() available." -test('countOf', [1, 2, 1, 3, 1, 4], 1, 3) +if not os.isatty(master): + raise TestFailed, "Master-end of pty is not a terminal." +if not os.isatty(slave): + raise TestFailed, "Slave-end of pty is not a terminal." -a = [4, 3, 2, 1] -test('delitem', a, None, 1) -if a <> [4, 2, 1]: - print 'delitem() failed' +os.write(slave, 'Ping!') +print os.read(master, 1024) -a = range(10) -test('delslice', a, None, 2, 8) -if a <> [0, 1, 8, 9]: - print 'delslice() failed' - -a = range(10) -test('div', 5, 2, 2) -test('getitem', a, 2, 2) -test('getslice', a, [4, 5], 4, 6) -test('indexOf', [4, 3, 2, 1], 1, 3) -test('inv', 4, -5) -test('isCallable', 4, 0) -test('isCallable', operator.isCallable, 1) -test('isMappingType', operator.isMappingType, 0) -test('isMappingType', operator.__dict__, 1) -test('isNumberType', 8.3, 1) -test('isNumberType', dir(), 0) -test('isSequenceType', dir(), 1) -test('isSequenceType', 'yeahbuddy', 1) -test('isSequenceType', 3, 0) -test('lshift', 5, 10, 1) -test('mod', 5, 1, 2) -test('mul', 5, 10, 2) -test('neg', 5, -5) -test('or_', 0xa, 0xf, 0x5) -test('pos', -5, -5) - -a = range(3) -test('repeat', a, a+a, 2) -test('rshift', 5, 2, 1) - -test('sequenceIncludes', range(4), 1, 2) -test('sequenceIncludes', range(4), 0, 5) - -test('setitem', a, None, 0, 2) -if a <> [2, 1, 2]: - print 'setitem() failed' - -a = range(4) -test('setslice', a, None, 1, 3, [2, 1]) -if a <> [0, 2, 1, 3]: - print 'setslice() failed:', a - -test('sub', 5, 2, 3) -test('truth', 5, 1) -test('truth', [], 0) -test('xor', 0xb, 0x7, 0xc) - - -# some negative tests -test('indexOf', [4, 3, 2, 1], ValueError, 9) diff --git a/Lib/dos-8x3/test_pop.py b/Lib/dos-8x3/test_pop.py index be79f3c..26ef9d9 100644 --- a/Lib/dos-8x3/test_pop.py +++ b/Lib/dos-8x3/test_pop.py @@ -3,15 +3,54 @@ Christian Tismer """ +import os + # popen2 contains its own testing routine # which is especially useful to see if open files -# like stdin can be read successfully by a forked +# like stdin can be read successfully by a forked # subprocess. def main(): - from os import fork # skips test through ImportError + print "Test popen2 module:" + try: + from os import popen + except ImportError: + # if we don't have os.popen, check that + # we have os.fork. if not, skip the test + # (by raising an ImportError) + from os import fork import popen2 popen2._test() -main() +def _test(): + # same test as popen2._test(), but using the os.popen*() API + print "Testing os module:" + import popen2 + cmd = "cat" + teststr = "abc\n" + resultstr = teststr + if os.name == "nt": + cmd = "more" + resultstr = "\n" + resultstr + print "testing popen2..." + w, r = os.popen2(cmd) + w.write(teststr) + w.close() + assert r.read() == resultstr + print "testing popen3..." + try: + w, r, e = os.popen3([cmd]) + except: + w, r, e = os.popen3(cmd) + w.write(teststr) + w.close() + assert r.read() == resultstr + assert e.read() == "" + for inst in popen2._active[:]: + inst.wait() + assert not popen2._active + print "All OK" + +main() +_test() diff --git a/Lib/dos-8x3/test_rgb.py b/Lib/dos-8x3/test_rgb.py index 38bcdf5..1fa201d 100755 --- a/Lib/dos-8x3/test_rgb.py +++ b/Lib/dos-8x3/test_rgb.py @@ -4,7 +4,8 @@ import rgbimg, os, uu from test_support import verbose, unlink, findfile -error = 'test_rgbimg.error' +class error(Exception): + pass print 'RGBimg test suite:' diff --git a/Lib/dos-8x3/test_sel.py b/Lib/dos-8x3/test_sel.py index 60de360..b198cf1 100755 --- a/Lib/dos-8x3/test_sel.py +++ b/Lib/dos-8x3/test_sel.py @@ -45,7 +45,6 @@ def test(): if verbose: print 'timeout =', tout rfd, wfd, xfd = select.select([p], [], [], tout) -## print rfd, wfd, xfd if (rfd, wfd, xfd) == ([], [], []): continue if (rfd, wfd, xfd) == ([p], [], []): @@ -57,7 +56,7 @@ def test(): print 'EOF' break continue - print 'Heh?' + print 'Unexpected return values from select():', rfd, wfd, xfd p.close() test() diff --git a/Lib/dos-8x3/test_sig.py b/Lib/dos-8x3/test_sig.py index 2d33635..02b5dc3 100755 --- a/Lib/dos-8x3/test_sig.py +++ b/Lib/dos-8x3/test_sig.py @@ -1,11 +1,11 @@ # Test the signal module -from test_support import verbose +from test_support import verbose, TestSkipped import signal import os import sys if sys.platform[:3] in ('win', 'os2'): - raise ImportError, "Can't test signal on %s" % sys.platform[:3] + raise TestSkipped, "Can't test signal on %s" % sys.platform[:3] if verbose: x = '-x' diff --git a/Lib/dos-8x3/test_str.py b/Lib/dos-8x3/test_str.py index ec57c26..c713d05 100644 --- a/Lib/dos-8x3/test_str.py +++ b/Lib/dos-8x3/test_str.py @@ -1,185 +1,134 @@ -from test_support import verbose -import string, sys +#! /usr/bin/env python + +# Sanity checker for time.strftime -# XXX: kludge... short circuit if strings don't have methods -try: - ''.join -except AttributeError: - raise ImportError +import time, calendar, sys, string, os, re +from test_support import verbose -def test(name, input, output, *args): +def main(): + global verbose + now = time.time() + strftest(now) + 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 'string.%s%s =? %s... ' % (name, (input,) + args, output), + 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: - # Prefer string methods over string module functions + 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: - f = getattr(input, name) - value = apply(f, args) - except AttributeError: - f = getattr(string, name) - value = apply(f, (input,) + args) - except: - value = sys.exc_type - if value != output: - if verbose: - print 'no' - print f, `input`, `output`, `value` - else: - if verbose: - print 'yes' - -test('atoi', " 1 ", 1) -test('atoi', " 1x", ValueError) -test('atoi', " x1 ", ValueError) -test('atol', " 1 ", 1L) -test('atol', " 1x ", ValueError) -test('atol', " x1 ", ValueError) -test('atof', " 1 ", 1.0) -test('atof', " 1x ", ValueError) -test('atof', " x1 ", ValueError) - -test('capitalize', ' hello ', ' hello ') -test('capitalize', 'hello ', 'Hello ') -test('find', 'abcdefghiabc', 0, 'abc') -test('find', 'abcdefghiabc', 9, 'abc', 1) -test('find', 'abcdefghiabc', -1, 'def', 4) -test('rfind', 'abcdefghiabc', 9, 'abc') -test('lower', 'HeLLo', 'hello') -test('lower', 'hello', 'hello') -test('upper', 'HeLLo', 'HELLO') -test('upper', 'HELLO', 'HELLO') - -test('title', ' hello ', ' Hello ') -test('title', 'hello ', 'Hello ') -test('title', "fOrMaT thIs aS titLe String", 'Format This As Title String') -test('title', "fOrMaT,thIs-aS*titLe;String", 'Format,This-As*Title;String') -test('title', "getInt", 'Getint') - -test('expandtabs', 'abc\rab\tdef\ng\thi', 'abc\rab def\ng hi') -test('expandtabs', 'abc\rab\tdef\ng\thi', 'abc\rab def\ng hi', 8) -test('expandtabs', 'abc\rab\tdef\ng\thi', 'abc\rab def\ng hi', 4) -test('expandtabs', 'abc\r\nab\tdef\ng\thi', 'abc\r\nab def\ng hi', 4) - -test('islower', 'a', 1) -test('islower', 'A', 0) -test('islower', '\n', 0) -test('islower', 'abc', 1) -test('islower', 'aBc', 0) -test('islower', 'abc\n', 1) - -test('isupper', 'a', 0) -test('isupper', 'A', 1) -test('isupper', '\n', 0) -test('isupper', 'ABC', 1) -test('isupper', 'AbC', 0) -test('isupper', 'ABC\n', 1) - -test('istitle', 'a', 0) -test('istitle', 'A', 1) -test('istitle', '\n', 0) -test('istitle', 'A Titlecased Line', 1) -test('istitle', 'A\nTitlecased Line', 1) -test('istitle', 'A Titlecased, Line', 1) -test('istitle', 'Not a capitalized String', 0) -test('istitle', 'Not\ta Titlecase String', 0) -test('istitle', 'Not--a Titlecase String', 0) - -test('splitlines', "abc\ndef\n\rghi", ['abc', 'def', '', 'ghi']) -test('splitlines', "abc\ndef\n\r\nghi", ['abc', 'def', '', 'ghi']) -test('splitlines', "abc\ndef\r\nghi", ['abc', 'def', 'ghi']) -test('splitlines', "abc\ndef\r\nghi\n", ['abc', 'def', 'ghi']) -test('splitlines', "abc\ndef\r\nghi\n\r", ['abc', 'def', 'ghi', '']) -test('splitlines', "\nabc\ndef\r\nghi\n\r", ['', 'abc', 'def', 'ghi', '']) -test('splitlines', "\nabc\ndef\r\nghi\n\r", ['\n', 'abc\n', 'def\r\n', 'ghi\n', '\r'], 1) - -transtable = '\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037 !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`xyzdefghijklmnopqrstuvwxyz{|}~\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377' - -test('maketrans', 'abc', transtable, 'xyz') -test('maketrans', 'abc', ValueError, 'xyzq') - -test('split', 'this is the split function', - ['this', 'is', 'the', 'split', 'function']) -test('split', 'a|b|c|d', ['a', 'b', 'c', 'd'], '|') -test('split', 'a|b|c|d', ['a', 'b', 'c|d'], '|', 2) -test('split', 'a b c d', ['a', 'b c d'], None, 1) -test('split', 'a b c d', ['a', 'b', 'c d'], None, 2) -test('split', 'a b c d', ['a', 'b', 'c', 'd'], None, 3) -test('split', 'a b c d', ['a', 'b', 'c', 'd'], None, 4) -test('split', 'a b c d', ['a b c d'], None, 0) -test('split', 'a b c d', ['a', 'b', 'c d'], None, 2) -test('split', 'a b c d ', ['a', 'b', 'c', 'd']) - -# join now works with any sequence type -class Sequence: - def __init__(self): self.seq = 'wxyz' - def __len__(self): return len(self.seq) - def __getitem__(self, i): return self.seq[i] - -test('join', ['a', 'b', 'c', 'd'], 'a b c d') -test('join', ('a', 'b', 'c', 'd'), 'abcd', '') -test('join', Sequence(), 'w x y z') -test('join', 7, TypeError) - -class BadSeq(Sequence): - def __init__(self): self.seq = [7, 'hello', 123L] - -test('join', BadSeq(), TypeError) - -# try a few long ones -print string.join(['x' * 100] * 100, ':') -print string.join(('x' * 100,) * 100, ':') - -test('strip', ' hello ', 'hello') -test('lstrip', ' hello ', 'hello ') -test('rstrip', ' hello ', ' hello') -test('strip', 'hello', 'hello') - -test('swapcase', 'HeLLo cOmpUteRs', 'hEllO CoMPuTErS') -test('translate', 'xyzabcdef', 'xyzxyz', transtable, 'def') - -table = string.maketrans('a', 'A') -test('translate', 'abc', 'Abc', table) -test('translate', 'xyz', 'xyz', table) - -test('replace', 'one!two!three!', 'one@two!three!', '!', '@', 1) -test('replace', 'one!two!three!', 'onetwothree', '!', '') -test('replace', 'one!two!three!', 'one@two@three!', '!', '@', 2) -test('replace', 'one!two!three!', 'one@two@three@', '!', '@', 3) -test('replace', 'one!two!three!', 'one@two@three@', '!', '@', 4) -test('replace', 'one!two!three!', 'one!two!three!', '!', '@', 0) -test('replace', 'one!two!three!', 'one@two@three@', '!', '@') -test('replace', 'one!two!three!', 'one!two!three!', 'x', '@') -test('replace', 'one!two!three!', 'one!two!three!', 'x', '@', 2) - -test('startswith', 'hello', 1, 'he') -test('startswith', 'hello', 1, 'hello') -test('startswith', 'hello', 0, 'hello world') -test('startswith', 'hello', 1, '') -test('startswith', 'hello', 0, 'ello') -test('startswith', 'hello', 1, 'ello', 1) -test('startswith', 'hello', 1, 'o', 4) -test('startswith', 'hello', 0, 'o', 5) -test('startswith', 'hello', 1, '', 5) -test('startswith', 'hello', 0, 'lo', 6) -test('startswith', 'helloworld', 1, 'lowo', 3) -test('startswith', 'helloworld', 1, 'lowo', 3, 7) -test('startswith', 'helloworld', 0, 'lowo', 3, 6) - -test('endswith', 'hello', 1, 'lo') -test('endswith', 'hello', 0, 'he') -test('endswith', 'hello', 1, '') -test('endswith', 'hello', 0, 'hello world') -test('endswith', 'helloworld', 0, 'worl') -test('endswith', 'helloworld', 1, 'worl', 3, 9) -test('endswith', 'helloworld', 1, 'world', 3, 12) -test('endswith', 'helloworld', 1, 'lowo', 1, 7) -test('endswith', 'helloworld', 1, 'lowo', 2, 7) -test('endswith', 'helloworld', 1, 'lowo', 3, 7) -test('endswith', 'helloworld', 0, 'lowo', 4, 7) -test('endswith', 'helloworld', 0, 'lowo', 3, 8) -test('endswith', 'ab', 0, 'ab', 0, 1) -test('endswith', 'ab', 0, 'ab', 0, 0) - -string.whitespace -string.lowercase -string.uppercase + 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() diff --git a/Lib/dos-8x3/test_sup.py b/Lib/dos-8x3/test_sup.py index 3839c79..99bacda 100755 --- a/Lib/dos-8x3/test_sup.py +++ b/Lib/dos-8x3/test_sup.py @@ -1,8 +1,26 @@ -# Python test set -- supporting definitions. +"""Supporting definitions for the Python regression test.""" + + +class Error(Exception): + """Base class for regression test exceptions.""" + +class TestFailed(Error): + """Test failed.""" + +class TestSkipped(Error): + """Test skipped. + + This can be raised to indicate that a test was deliberatly + skipped, but not because a feature wasn't available. For + example, if some resource can't be used, such as the network + appears to be unavailable, this should be raised instead of + TestFailed. + + """ -TestFailed = 'test_support -- test failed' # Exception verbose = 1 # Flag set to 0 by regrtest.py +use_large_resources = 1 # Flag set to 0 by regrtest.py def unload(name): import sys diff --git a/Lib/dos-8x3/test_tim.py b/Lib/dos-8x3/test_tim.py index 5dbc895..03d081e 100644 --- a/Lib/dos-8x3/test_tim.py +++ b/Lib/dos-8x3/test_tim.py @@ -1,21 +1,39 @@ -from test_support import verbose -import timing +import time -r = range(100000) -if verbose: - print 'starting...' -timing.start() -for i in r: - pass -timing.finish() -if verbose: - print 'finished' +time.altzone +time.clock() +t = time.time() +time.asctime(time.gmtime(t)) +if time.ctime(t) <> time.asctime(time.localtime(t)): + print 'time.ctime(t) <> time.asctime(time.localtime(t))' + +time.daylight +if long(time.mktime(time.localtime(t))) <> long(t): + print 'time.mktime(time.localtime(t)) <> t' + +time.sleep(1.2) +tt = time.gmtime(t) +for directive in ('a', 'A', 'b', 'B', 'c', 'd', 'H', 'I', + 'j', 'm', 'M', 'p', 'S', + 'U', 'w', 'W', 'x', 'X', 'y', 'Y', 'Z', '%'): + format = ' %' + directive + try: + time.strftime(format, tt) + except ValueError: + print 'conversion specifier:', format, ' failed.' -secs = timing.seconds() -milli = timing.milli() -micro = timing.micro() +time.timezone +time.tzname -if verbose: - print 'seconds:', secs - print 'milli :', milli - print 'micro :', micro +# expected errors +try: + time.asctime(0) +except TypeError: + pass + +try: + time.mktime((999999, 999999, 999999, 999999, + 999999, 999999, 999999, 999999, + 999999)) +except OverflowError: + pass diff --git a/Lib/dos-8x3/test_typ.py b/Lib/dos-8x3/test_typ.py index e22b0e2..e3a51f0 100755 --- a/Lib/dos-8x3/test_typ.py +++ b/Lib/dos-8x3/test_typ.py @@ -253,3 +253,15 @@ if d.get('c') != None: raise TestFailed, 'missing dict get, no 2nd arg' if d.get('c', 3) != 3: raise TestFailed, 'missing dict get, w/ 2nd arg' if d.get('a') != 1: raise TestFailed, 'present dict get, no 2nd arg' if d.get('a', 3) != 1: raise TestFailed, 'present dict get, w/ 2nd arg' +# dict.setdefault() +d = {} +if d.setdefault('key0') <> None: + raise TestFailed, 'missing {} setdefault, no 2nd arg' +if d.setdefault('key0') <> None: + raise TestFailed, 'present {} setdefault, no 2nd arg' +d.setdefault('key', []).append(3) +if d['key'][0] <> 3: + raise TestFailed, 'missing {} setdefault, w/ 2nd arg' +d.setdefault('key', []).append(4) +if len(d['key']) <> 2: + raise TestFailed, 'present {} setdefault, w/ 2nd arg' diff --git a/Lib/dos-8x3/test_uni.py b/Lib/dos-8x3/test_uni.py index 6ddd077..8479c20 100644 --- a/Lib/dos-8x3/test_uni.py +++ b/Lib/dos-8x3/test_uni.py @@ -1,50 +1,517 @@ -""" Test script for the unicodedata module. +""" Test script for the Unicode implementation. Written by Marc-Andre Lemburg (mal@lemburg.com). (c) Copyright CNRI, All Rights Reserved. NO WARRANTY. -"""#" +""" from test_support import verbose import sys -# Test Unicode database APIs -import unicodedata +def test(method, input, output, *args): + if verbose: + print '%s.%s%s =? %s... ' % (repr(input), method, args, output), + try: + f = getattr(input, method) + value = apply(f, args) + except: + value = sys.exc_type + exc = sys.exc_info()[:2] + else: + exc = None + if value != output: + if verbose: + print 'no' + print '*',f, `input`, `output`, `value` + if exc: + print ' value == %s: %s' % (exc) + else: + if verbose: + print 'yes' -print 'Testing unicodedata module...', +test('capitalize', u' hello ', u' hello ') +test('capitalize', u'hello ', u'Hello ') -assert unicodedata.digit(u'A',None) is None -assert unicodedata.digit(u'9') == 9 -assert unicodedata.digit(u'\u215b',None) is None -assert unicodedata.digit(u'\u2468') == 9 +test('title', u' hello ', u' Hello ') +test('title', u'hello ', u'Hello ') +test('title', u"fOrMaT thIs aS titLe String", u'Format This As Title String') +test('title', u"fOrMaT,thIs-aS*titLe;String", u'Format,This-As*Title;String') +test('title', u"getInt", u'Getint') -assert unicodedata.numeric(u'A',None) is None -assert unicodedata.numeric(u'9') == 9 -assert unicodedata.numeric(u'\u215b') == 0.125 -assert unicodedata.numeric(u'\u2468') == 9.0 +test('find', u'abcdefghiabc', 0, u'abc') +test('find', u'abcdefghiabc', 9, u'abc', 1) +test('find', u'abcdefghiabc', -1, u'def', 4) -assert unicodedata.decimal(u'A',None) is None -assert unicodedata.decimal(u'9') == 9 -assert unicodedata.decimal(u'\u215b',None) is None -assert unicodedata.decimal(u'\u2468',None) is None +test('rfind', u'abcdefghiabc', 9, u'abc') -assert unicodedata.category(u'\uFFFE') == 'Cn' -assert unicodedata.category(u'a') == 'Ll' -assert unicodedata.category(u'A') == 'Lu' +test('lower', u'HeLLo', u'hello') +test('lower', u'hello', u'hello') -assert unicodedata.bidirectional(u'\uFFFE') == '' -assert unicodedata.bidirectional(u' ') == 'WS' -assert unicodedata.bidirectional(u'A') == 'L' +test('upper', u'HeLLo', u'HELLO') +test('upper', u'HELLO', u'HELLO') -assert unicodedata.decomposition(u'\uFFFE') == '' -assert unicodedata.decomposition(u'\u00bc') == '<fraction> 0031 2044 0034' +if 0: + transtable = '\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037 !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`xyzdefghijklmnopqrstuvwxyz{|}~\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377' -assert unicodedata.mirrored(u'\uFFFE') == 0 -assert unicodedata.mirrored(u'a') == 0 -assert unicodedata.mirrored(u'\u2201') == 1 + test('maketrans', u'abc', transtable, u'xyz') + test('maketrans', u'abc', ValueError, u'xyzq') -assert unicodedata.combining(u'\uFFFE') == 0 -assert unicodedata.combining(u'a') == 0 -assert unicodedata.combining(u'\u20e1') == 230 +test('split', u'this is the split function', + [u'this', u'is', u'the', u'split', u'function']) +test('split', u'a|b|c|d', [u'a', u'b', u'c', u'd'], u'|') +test('split', u'a|b|c|d', [u'a', u'b', u'c|d'], u'|', 2) +test('split', u'a b c d', [u'a', u'b c d'], None, 1) +test('split', u'a b c d', [u'a', u'b', u'c d'], None, 2) +test('split', u'a b c d', [u'a', u'b', u'c', u'd'], None, 3) +test('split', u'a b c d', [u'a', u'b', u'c', u'd'], None, 4) +test('split', u'a b c d', [u'a b c d'], None, 0) +test('split', u'a b c d', [u'a', u'b', u'c d'], None, 2) +test('split', u'a b c d ', [u'a', u'b', u'c', u'd']) +# join now works with any sequence type +class Sequence: + def __init__(self): self.seq = 'wxyz' + def __len__(self): return len(self.seq) + def __getitem__(self, i): return self.seq[i] + +test('join', u' ', u'a b c d', [u'a', u'b', u'c', u'd']) +test('join', u'', u'abcd', (u'a', u'b', u'c', u'd')) +test('join', u' ', u'w x y z', Sequence()) +test('join', u' ', TypeError, 7) + +class BadSeq(Sequence): + def __init__(self): self.seq = [7, u'hello', 123L] + +test('join', u' ', TypeError, BadSeq()) + +result = u'' +for i in range(10): + if i > 0: + result = result + u':' + result = result + u'x'*10 +test('join', u':', result, [u'x' * 10] * 10) +test('join', u':', result, (u'x' * 10,) * 10) + +test('strip', u' hello ', u'hello') +test('lstrip', u' hello ', u'hello ') +test('rstrip', u' hello ', u' hello') +test('strip', u'hello', u'hello') + +test('swapcase', u'HeLLo cOmpUteRs', u'hEllO CoMPuTErS') + +if 0: + test('translate', u'xyzabcdef', u'xyzxyz', transtable, u'def') + + table = string.maketrans('a', u'A') + test('translate', u'abc', u'Abc', table) + test('translate', u'xyz', u'xyz', table) + +test('replace', u'one!two!three!', u'one@two!three!', u'!', u'@', 1) +test('replace', u'one!two!three!', u'onetwothree', '!', '') +test('replace', u'one!two!three!', u'one@two@three!', u'!', u'@', 2) +test('replace', u'one!two!three!', u'one@two@three@', u'!', u'@', 3) +test('replace', u'one!two!three!', u'one@two@three@', u'!', u'@', 4) +test('replace', u'one!two!three!', u'one!two!three!', u'!', u'@', 0) +test('replace', u'one!two!three!', u'one@two@three@', u'!', u'@') +test('replace', u'one!two!three!', u'one!two!three!', u'x', u'@') +test('replace', u'one!two!three!', u'one!two!three!', u'x', u'@', 2) + +test('startswith', u'hello', 1, u'he') +test('startswith', u'hello', 1, u'hello') +test('startswith', u'hello', 0, u'hello world') +test('startswith', u'hello', 1, u'') +test('startswith', u'hello', 0, u'ello') +test('startswith', u'hello', 1, u'ello', 1) +test('startswith', u'hello', 1, u'o', 4) +test('startswith', u'hello', 0, u'o', 5) +test('startswith', u'hello', 1, u'', 5) +test('startswith', u'hello', 0, u'lo', 6) +test('startswith', u'helloworld', 1, u'lowo', 3) +test('startswith', u'helloworld', 1, u'lowo', 3, 7) +test('startswith', u'helloworld', 0, u'lowo', 3, 6) + +test('endswith', u'hello', 1, u'lo') +test('endswith', u'hello', 0, u'he') +test('endswith', u'hello', 1, u'') +test('endswith', u'hello', 0, u'hello world') +test('endswith', u'helloworld', 0, u'worl') +test('endswith', u'helloworld', 1, u'worl', 3, 9) +test('endswith', u'helloworld', 1, u'world', 3, 12) +test('endswith', u'helloworld', 1, u'lowo', 1, 7) +test('endswith', u'helloworld', 1, u'lowo', 2, 7) +test('endswith', u'helloworld', 1, u'lowo', 3, 7) +test('endswith', u'helloworld', 0, u'lowo', 4, 7) +test('endswith', u'helloworld', 0, u'lowo', 3, 8) +test('endswith', u'ab', 0, u'ab', 0, 1) +test('endswith', u'ab', 0, u'ab', 0, 0) + +test('expandtabs', u'abc\rab\tdef\ng\thi', u'abc\rab def\ng hi') +test('expandtabs', u'abc\rab\tdef\ng\thi', u'abc\rab def\ng hi', 8) +test('expandtabs', u'abc\rab\tdef\ng\thi', u'abc\rab def\ng hi', 4) +test('expandtabs', u'abc\r\nab\tdef\ng\thi', u'abc\r\nab def\ng hi', 4) + +if 0: + test('capwords', u'abc def ghi', u'Abc Def Ghi') + test('capwords', u'abc\tdef\nghi', u'Abc Def Ghi') + test('capwords', u'abc\t def \nghi', u'Abc Def Ghi') + +# Comparisons: +print 'Testing Unicode comparisons...', +assert u'abc' == 'abc' +assert 'abc' == u'abc' +assert u'abc' == u'abc' +assert u'abcd' > 'abc' +assert 'abcd' > u'abc' +assert u'abcd' > u'abc' +assert u'abc' < 'abcd' +assert 'abc' < u'abcd' +assert u'abc' < u'abcd' +print 'done.' + +if 0: + # Move these tests to a Unicode collation module test... + + print 'Testing UTF-16 code point order comparisons...', + #No surrogates, no fixup required. + assert u'\u0061' < u'\u20ac' + # Non surrogate below surrogate value, no fixup required + assert u'\u0061' < u'\ud800\udc02' + + # Non surrogate above surrogate value, fixup required + def test_lecmp(s, s2): + assert s < s2 , "comparison failed on %s < %s" % (s, s2) + + def test_fixup(s): + s2 = u'\ud800\udc01' + test_lecmp(s, s2) + s2 = u'\ud900\udc01' + test_lecmp(s, s2) + s2 = u'\uda00\udc01' + test_lecmp(s, s2) + s2 = u'\udb00\udc01' + test_lecmp(s, s2) + s2 = u'\ud800\udd01' + test_lecmp(s, s2) + s2 = u'\ud900\udd01' + test_lecmp(s, s2) + s2 = u'\uda00\udd01' + test_lecmp(s, s2) + s2 = u'\udb00\udd01' + test_lecmp(s, s2) + s2 = u'\ud800\ude01' + test_lecmp(s, s2) + s2 = u'\ud900\ude01' + test_lecmp(s, s2) + s2 = u'\uda00\ude01' + test_lecmp(s, s2) + s2 = u'\udb00\ude01' + test_lecmp(s, s2) + s2 = u'\ud800\udfff' + test_lecmp(s, s2) + s2 = u'\ud900\udfff' + test_lecmp(s, s2) + s2 = u'\uda00\udfff' + test_lecmp(s, s2) + s2 = u'\udb00\udfff' + test_lecmp(s, s2) + + test_fixup(u'\ue000') + test_fixup(u'\uff61') + + # Surrogates on both sides, no fixup required + assert u'\ud800\udc02' < u'\ud84d\udc56' + print 'done.' + +test('ljust', u'abc', u'abc ', 10) +test('rjust', u'abc', u' abc', 10) +test('center', u'abc', u' abc ', 10) +test('ljust', u'abc', u'abc ', 6) +test('rjust', u'abc', u' abc', 6) +test('center', u'abc', u' abc ', 6) +test('ljust', u'abc', u'abc', 2) +test('rjust', u'abc', u'abc', 2) +test('center', u'abc', u'abc', 2) + +test('islower', u'a', 1) +test('islower', u'A', 0) +test('islower', u'\n', 0) +test('islower', u'\u1FFc', 0) +test('islower', u'abc', 1) +test('islower', u'aBc', 0) +test('islower', u'abc\n', 1) + +test('isupper', u'a', 0) +test('isupper', u'A', 1) +test('isupper', u'\n', 0) +test('isupper', u'\u1FFc', 0) +test('isupper', u'ABC', 1) +test('isupper', u'AbC', 0) +test('isupper', u'ABC\n', 1) + +test('istitle', u'a', 0) +test('istitle', u'A', 1) +test('istitle', u'\n', 0) +test('istitle', u'\u1FFc', 1) +test('istitle', u'A Titlecased Line', 1) +test('istitle', u'A\nTitlecased Line', 1) +test('istitle', u'A Titlecased, Line', 1) +test('istitle', u'Greek \u1FFcitlecases ...', 1) +test('istitle', u'Not a capitalized String', 0) +test('istitle', u'Not\ta Titlecase String', 0) +test('istitle', u'Not--a Titlecase String', 0) + +test('isalpha', u'a', 1) +test('isalpha', u'A', 1) +test('isalpha', u'\n', 0) +test('isalpha', u'\u1FFc', 1) +test('isalpha', u'abc', 1) +test('isalpha', u'aBc123', 0) +test('isalpha', u'abc\n', 0) + +test('isalnum', u'a', 1) +test('isalnum', u'A', 1) +test('isalnum', u'\n', 0) +test('isalnum', u'123abc456', 1) +test('isalnum', u'a1b3c', 1) +test('isalnum', u'aBc000 ', 0) +test('isalnum', u'abc\n', 0) + +test('splitlines', u"abc\ndef\n\rghi", [u'abc', u'def', u'', u'ghi']) +test('splitlines', u"abc\ndef\n\r\nghi", [u'abc', u'def', u'', u'ghi']) +test('splitlines', u"abc\ndef\r\nghi", [u'abc', u'def', u'ghi']) +test('splitlines', u"abc\ndef\r\nghi\n", [u'abc', u'def', u'ghi']) +test('splitlines', u"abc\ndef\r\nghi\n\r", [u'abc', u'def', u'ghi', u'']) +test('splitlines', u"\nabc\ndef\r\nghi\n\r", [u'', u'abc', u'def', u'ghi', u'']) +test('splitlines', u"\nabc\ndef\r\nghi\n\r", [u'\n', u'abc\n', u'def\r\n', u'ghi\n', u'\r'], 1) + +test('translate', u"abababc", u'bbbc', {ord('a'):None}) +test('translate', u"abababc", u'iiic', {ord('a'):None, ord('b'):ord('i')}) +test('translate', u"abababc", u'iiix', {ord('a'):None, ord('b'):ord('i'), ord('c'):u'x'}) + +# Contains: +print 'Testing Unicode contains method...', +assert ('a' in u'abdb') == 1 +assert ('a' in u'bdab') == 1 +assert ('a' in u'bdaba') == 1 +assert ('a' in u'bdba') == 1 +assert ('a' in u'bdba') == 1 +assert (u'a' in u'bdba') == 1 +assert (u'a' in u'bdb') == 0 +assert (u'a' in 'bdb') == 0 +assert (u'a' in 'bdba') == 1 +assert (u'a' in ('a',1,None)) == 1 +assert (u'a' in (1,None,'a')) == 1 +assert (u'a' in (1,None,u'a')) == 1 +assert ('a' in ('a',1,None)) == 1 +assert ('a' in (1,None,'a')) == 1 +assert ('a' in (1,None,u'a')) == 1 +assert ('a' in ('x',1,u'y')) == 0 +assert ('a' in ('x',1,None)) == 0 +print 'done.' + +# Formatting: +print 'Testing Unicode formatting strings...', +assert u"%s, %s" % (u"abc", "abc") == u'abc, abc' +assert u"%s, %s, %i, %f, %5.2f" % (u"abc", "abc", 1, 2, 3) == u'abc, abc, 1, 2.000000, 3.00' +assert u"%s, %s, %i, %f, %5.2f" % (u"abc", "abc", 1, -2, 3) == u'abc, abc, 1, -2.000000, 3.00' +assert u"%s, %s, %i, %f, %5.2f" % (u"abc", "abc", -1, -2, 3.5) == u'abc, abc, -1, -2.000000, 3.50' +assert u"%s, %s, %i, %f, %5.2f" % (u"abc", "abc", -1, -2, 3.57) == u'abc, abc, -1, -2.000000, 3.57' +assert u"%s, %s, %i, %f, %5.2f" % (u"abc", "abc", -1, -2, 1003.57) == u'abc, abc, -1, -2.000000, 1003.57' +assert u"%c" % (u"a",) == u'a' +assert u"%c" % ("a",) == u'a' +assert u"%c" % (34,) == u'"' +assert u"%c" % (36,) == u'$' +value = u"%r, %r" % (u"abc", "abc") +if value != u"u'abc', 'abc'": + print '*** formatting failed for "%s"' % 'u"%r, %r" % (u"abc", "abc")' + +assert u"%(x)s, %(y)s" % {'x':u"abc", 'y':"def"} == u'abc, def' +try: + value = u"%(x)s, %(ä)s" % {'x':u"abc", u'ä'.encode('utf-8'):"def"} +except KeyError: + print '*** formatting failed for "%s"' % "u'abc, def'" +else: + assert value == u'abc, def' + +# formatting jobs delegated from the string implementation: +assert '...%(foo)s...' % {'foo':u"abc"} == u'...abc...' +assert '...%(foo)s...' % {'foo':"abc"} == '...abc...' +assert '...%(foo)s...' % {u'foo':"abc"} == '...abc...' +assert '...%(foo)s...' % {u'foo':u"abc"} == u'...abc...' +assert '...%(foo)s...' % {u'foo':u"abc",'def':123} == u'...abc...' +assert '...%(foo)s...' % {u'foo':u"abc",u'def':123} == u'...abc...' +assert '...%s...%s...%s...%s...' % (1,2,3,u"abc") == u'...1...2...3...abc...' +assert '...%s...' % u"abc" == u'...abc...' print 'done.' + +# Test builtin codecs +print 'Testing builtin codecs...', + +# UTF-8 specific encoding tests: +assert u'\u20ac'.encode('utf-8') == \ + ''.join((chr(0xe2), chr(0x82), chr(0xac))) +assert u'\ud800\udc02'.encode('utf-8') == \ + ''.join((chr(0xf0), chr(0x90), chr(0x80), chr(0x82))) +assert u'\ud84d\udc56'.encode('utf-8') == \ + ''.join((chr(0xf0), chr(0xa3), chr(0x91), chr(0x96))) +# UTF-8 specific decoding tests +assert unicode(''.join((chr(0xf0), chr(0xa3), chr(0x91), chr(0x96))), + 'utf-8') == u'\ud84d\udc56' +assert unicode(''.join((chr(0xf0), chr(0x90), chr(0x80), chr(0x82))), + 'utf-8') == u'\ud800\udc02' +assert unicode(''.join((chr(0xe2), chr(0x82), chr(0xac))), + 'utf-8') == u'\u20ac' + +# Other possible utf-8 test cases: +# * strict decoding testing for all of the +# UTF8_ERROR cases in PyUnicode_DecodeUTF8 + + + +assert unicode('hello','ascii') == u'hello' +assert unicode('hello','utf-8') == u'hello' +assert unicode('hello','utf8') == u'hello' +assert unicode('hello','latin-1') == u'hello' + +class String: + x = '' + def __str__(self): + return self.x + +o = String() + +o.x = 'abc' +assert unicode(o) == u'abc' +assert str(o) == 'abc' + +o.x = u'abc' +assert unicode(o) == u'abc' +assert str(o) == 'abc' + +try: + u'Andr\202 x'.encode('ascii') + u'Andr\202 x'.encode('ascii','strict') +except ValueError: + pass +else: + raise AssertionError, "u'Andr\202'.encode('ascii') failed to raise an exception" +assert u'Andr\202 x'.encode('ascii','ignore') == "Andr x" +assert u'Andr\202 x'.encode('ascii','replace') == "Andr? x" + +try: + unicode('Andr\202 x','ascii') + unicode('Andr\202 x','ascii','strict') +except ValueError: + pass +else: + raise AssertionError, "unicode('Andr\202') failed to raise an exception" +assert unicode('Andr\202 x','ascii','ignore') == u"Andr x" +assert unicode('Andr\202 x','ascii','replace') == u'Andr\uFFFD x' + +assert u'hello'.encode('ascii') == 'hello' +assert u'hello'.encode('utf-8') == 'hello' +assert u'hello'.encode('utf8') == 'hello' +assert u'hello'.encode('utf-16-le') == 'h\000e\000l\000l\000o\000' +assert u'hello'.encode('utf-16-be') == '\000h\000e\000l\000l\000o' +assert u'hello'.encode('latin-1') == 'hello' + +u = u''.join(map(unichr, range(1024))) +for encoding in ('utf-8', 'utf-16', 'utf-16-le', 'utf-16-be', + 'raw_unicode_escape', 'unicode_escape', 'unicode_internal'): + assert unicode(u.encode(encoding),encoding) == u + +u = u''.join(map(unichr, range(256))) +for encoding in ( + 'latin-1', + ): + try: + assert unicode(u.encode(encoding),encoding) == u + except AssertionError: + print '*** codec "%s" failed round-trip' % encoding + except ValueError,why: + print '*** codec for "%s" failed: %s' % (encoding, why) + +u = u''.join(map(unichr, range(128))) +for encoding in ( + 'ascii', + ): + try: + assert unicode(u.encode(encoding),encoding) == u + except AssertionError: + print '*** codec "%s" failed round-trip' % encoding + except ValueError,why: + print '*** codec for "%s" failed: %s' % (encoding, why) + +print 'done.' + +print 'Testing standard mapping codecs...', + +print '0-127...', +s = ''.join(map(chr, range(128))) +for encoding in ( + 'cp037', 'cp1026', + 'cp437', 'cp500', 'cp737', 'cp775', 'cp850', + 'cp852', 'cp855', 'cp860', 'cp861', 'cp862', + 'cp863', 'cp865', 'cp866', + 'iso8859_10', 'iso8859_13', 'iso8859_14', 'iso8859_15', + 'iso8859_2', 'iso8859_3', 'iso8859_4', 'iso8859_5', 'iso8859_6', + 'iso8859_7', 'iso8859_9', 'koi8_r', 'latin_1', + 'mac_cyrillic', 'mac_latin2', + + 'cp1250', 'cp1251', 'cp1252', 'cp1253', 'cp1254', 'cp1255', + 'cp1256', 'cp1257', 'cp1258', + 'cp856', 'cp857', 'cp864', 'cp869', 'cp874', + + 'mac_greek', 'mac_iceland','mac_roman', 'mac_turkish', + 'cp1006', 'cp875', 'iso8859_8', + + ### These have undefined mappings: + #'cp424', + + ): + try: + assert unicode(s,encoding).encode(encoding) == s + except AssertionError: + print '*** codec "%s" failed round-trip' % encoding + except ValueError,why: + print '*** codec for "%s" failed: %s' % (encoding, why) + +print '128-255...', +s = ''.join(map(chr, range(128,256))) +for encoding in ( + 'cp037', 'cp1026', + 'cp437', 'cp500', 'cp737', 'cp775', 'cp850', + 'cp852', 'cp855', 'cp860', 'cp861', 'cp862', + 'cp863', 'cp865', 'cp866', + 'iso8859_10', 'iso8859_13', 'iso8859_14', 'iso8859_15', + 'iso8859_2', 'iso8859_3', 'iso8859_4', 'iso8859_5', 'iso8859_6', + 'iso8859_7', 'iso8859_9', 'koi8_r', 'latin_1', + 'mac_cyrillic', 'mac_latin2', + + ### These have undefined mappings: + #'cp1250', 'cp1251', 'cp1252', 'cp1253', 'cp1254', 'cp1255', + #'cp1256', 'cp1257', 'cp1258', + #'cp424', 'cp856', 'cp857', 'cp864', 'cp869', 'cp874', + #'mac_greek', 'mac_iceland','mac_roman', 'mac_turkish', + + ### These fail the round-trip: + #'cp1006', 'cp875', 'iso8859_8', + + ): + try: + assert unicode(s,encoding).encode(encoding) == s + except AssertionError: + print '*** codec "%s" failed round-trip' % encoding + except ValueError,why: + print '*** codec for "%s" failed: %s' % (encoding, why) + +print 'done.' + +print 'Testing Unicode string concatenation...', +assert (u"abc" u"def") == u"abcdef" +assert ("abc" u"def") == u"abcdef" +assert (u"abc" "def") == u"abcdef" +assert (u"abc" u"def" "ghi") == u"abcdefghi" +assert ("abc" "def" u"ghi") == u"abcdefghi" +print 'done.' + diff --git a/Lib/dos-8x3/test_unp.py b/Lib/dos-8x3/test_unp.py index 1bfd478..25324c0 100644 --- a/Lib/dos-8x3/test_unp.py +++ b/Lib/dos-8x3/test_unp.py @@ -100,7 +100,8 @@ except ValueError: # unpacking a sequence where the test for too long raises a different # kind of error -BozoError = 'BozoError' +class BozoError(Exception): + pass class BadSeq: def __getitem__(self, i): diff --git a/Lib/dos-8x3/test_use.py b/Lib/dos-8x3/test_use.py index c12f1e2..63632f7 100644 --- a/Lib/dos-8x3/test_use.py +++ b/Lib/dos-8x3/test_use.py @@ -1,227 +1,101 @@ -#!/usr/bin/env python -import sys, string -from test_support import verbose -# UserString is a wrapper around the native builtin string type. -# UserString instances should behave similar to builtin string objects. -# The test cases were in part derived from 'test_string.py'. -from UserString import UserString - -if __name__ == "__main__": - verbose = 0 - -tested_methods = {} - -def test(methodname, input, *args): - global tested_methods - tested_methods[methodname] = 1 - if verbose: - print '%s.%s(%s) ' % (input, methodname, args), - u = UserString(input) - objects = [input, u, UserString(u)] - res = [""] * 3 - for i in range(3): - object = objects[i] - try: - f = getattr(object, methodname) - res[i] = apply(f, args) - except: - res[i] = sys.exc_type - if res[0] != res[1]: - if verbose: - print 'no' - print `input`, f, `res[0]`, "<>", `res[1]` - else: - if verbose: - print 'yes' - if res[1] != res[2]: - if verbose: - print 'no' - print `input`, f, `res[1]`, "<>", `res[2]` - else: - if verbose: - print 'yes' - -test('capitalize', ' hello ') -test('capitalize', 'hello ') - -test('center', 'foo', 0) -test('center', 'foo', 3) -test('center', 'foo', 16) - -test('ljust', 'foo', 0) -test('ljust', 'foo', 3) -test('ljust', 'foo', 16) - -test('rjust', 'foo', 0) -test('rjust', 'foo', 3) -test('rjust', 'foo', 16) - -test('count', 'abcabcabc', 'abc') -test('count', 'abcabcabc', 'abc', 1) -test('count', 'abcabcabc', 'abc', -1) -test('count', 'abcabcabc', 'abc', 7) -test('count', 'abcabcabc', 'abc', 0, 3) -test('count', 'abcabcabc', 'abc', 0, 333) - -test('find', 'abcdefghiabc', 'abc') -test('find', 'abcdefghiabc', 'abc', 1) -test('find', 'abcdefghiabc', 'def', 4) -test('rfind', 'abcdefghiabc', 'abc') - -test('index', 'abcabcabc', 'abc') -test('index', 'abcabcabc', 'abc', 1) -test('index', 'abcabcabc', 'abc', -1) -test('index', 'abcabcabc', 'abc', 7) -test('index', 'abcabcabc', 'abc', 0, 3) -test('index', 'abcabcabc', 'abc', 0, 333) - -test('rindex', 'abcabcabc', 'abc') -test('rindex', 'abcabcabc', 'abc', 1) -test('rindex', 'abcabcabc', 'abc', -1) -test('rindex', 'abcabcabc', 'abc', 7) -test('rindex', 'abcabcabc', 'abc', 0, 3) -test('rindex', 'abcabcabc', 'abc', 0, 333) - - -test('lower', 'HeLLo') -test('lower', 'hello') -test('upper', 'HeLLo') -test('upper', 'HELLO') - -test('title', ' hello ') -test('title', 'hello ') -test('title', "fOrMaT thIs aS titLe String") -test('title', "fOrMaT,thIs-aS*titLe;String") -test('title', "getInt") - -test('expandtabs', 'abc\rab\tdef\ng\thi') -test('expandtabs', 'abc\rab\tdef\ng\thi', 8) -test('expandtabs', 'abc\rab\tdef\ng\thi', 4) -test('expandtabs', 'abc\r\nab\tdef\ng\thi', 4) - -test('islower', 'a') -test('islower', 'A') -test('islower', '\n') -test('islower', 'abc') -test('islower', 'aBc') -test('islower', 'abc\n') - -test('isupper', 'a') -test('isupper', 'A') -test('isupper', '\n') -test('isupper', 'ABC') -test('isupper', 'AbC') -test('isupper', 'ABC\n') - -test('isdigit', ' 0123456789') -test('isdigit', '56789') -test('isdigit', '567.89') -test('isdigit', '0123456789abc') - -test('isspace', '') -test('isspace', ' ') -test('isspace', ' \t') -test('isspace', ' \t\f\n') - -test('istitle', 'a') -test('istitle', 'A') -test('istitle', '\n') -test('istitle', 'A Titlecased Line') -test('istitle', 'A\nTitlecased Line') -test('istitle', 'A Titlecased, Line') -test('istitle', 'Not a capitalized String') -test('istitle', 'Not\ta Titlecase String') -test('istitle', 'Not--a Titlecase String') - -test('splitlines', "abc\ndef\n\rghi") -test('splitlines', "abc\ndef\n\r\nghi") -test('splitlines', "abc\ndef\r\nghi") -test('splitlines', "abc\ndef\r\nghi\n") -test('splitlines', "abc\ndef\r\nghi\n\r") -test('splitlines', "\nabc\ndef\r\nghi\n\r") -test('splitlines', "\nabc\ndef\r\nghi\n\r") -test('splitlines', "\nabc\ndef\r\nghi\n\r") - -test('split', 'this is the split function') -test('split', 'a|b|c|d', '|') -test('split', 'a|b|c|d', '|', 2) -test('split', 'a b c d', None, 1) -test('split', 'a b c d', None, 2) -test('split', 'a b c d', None, 3) -test('split', 'a b c d', None, 4) -test('split', 'a b c d', None, 0) -test('split', 'a b c d', None, 2) -test('split', 'a b c d ') - -# join now works with any sequence type -class Sequence: - def __init__(self): self.seq = 'wxyz' - def __len__(self): return len(self.seq) - def __getitem__(self, i): return self.seq[i] - -test('join', '', ('a', 'b', 'c', 'd')) -test('join', '', Sequence()) -test('join', '', 7) - -class BadSeq(Sequence): - def __init__(self): self.seq = [7, 'hello', 123L] - -test('join', '', BadSeq()) - -test('strip', ' hello ') -test('lstrip', ' hello ') -test('rstrip', ' hello ') -test('strip', 'hello') - -test('swapcase', 'HeLLo cOmpUteRs') -transtable = string.maketrans("abc", "xyz") -test('translate', 'xyzabcdef', transtable, 'def') - -transtable = string.maketrans('a', 'A') -test('translate', 'abc', transtable) -test('translate', 'xyz', transtable) - -test('replace', 'one!two!three!', '!', '@', 1) -test('replace', 'one!two!three!', '!', '') -test('replace', 'one!two!three!', '!', '@', 2) -test('replace', 'one!two!three!', '!', '@', 3) -test('replace', 'one!two!three!', '!', '@', 4) -test('replace', 'one!two!three!', '!', '@', 0) -test('replace', 'one!two!three!', '!', '@') -test('replace', 'one!two!three!', 'x', '@') -test('replace', 'one!two!three!', 'x', '@', 2) - -test('startswith', 'hello', 'he') -test('startswith', 'hello', 'hello') -test('startswith', 'hello', 'hello world') -test('startswith', 'hello', '') -test('startswith', 'hello', 'ello') -test('startswith', 'hello', 'ello', 1) -test('startswith', 'hello', 'o', 4) -test('startswith', 'hello', 'o', 5) -test('startswith', 'hello', '', 5) -test('startswith', 'hello', 'lo', 6) -test('startswith', 'helloworld', 'lowo', 3) -test('startswith', 'helloworld', 'lowo', 3, 7) -test('startswith', 'helloworld', 'lowo', 3, 6) - -test('endswith', 'hello', 'lo') -test('endswith', 'hello', 'he') -test('endswith', 'hello', '') -test('endswith', 'hello', 'hello world') -test('endswith', 'helloworld', 'worl') -test('endswith', 'helloworld', 'worl', 3, 9) -test('endswith', 'helloworld', 'world', 3, 12) -test('endswith', 'helloworld', 'lowo', 1, 7) -test('endswith', 'helloworld', 'lowo', 2, 7) -test('endswith', 'helloworld', 'lowo', 3, 7) -test('endswith', 'helloworld', 'lowo', 4, 7) -test('endswith', 'helloworld', 'lowo', 3, 8) -test('endswith', 'ab', 'ab', 0, 1) -test('endswith', 'ab', 'ab', 0, 0) - -# TODO: test cases for: int, long, float, complex, +, * and cmp -s = "" -for builtin_method in dir(s): - if not tested_methods.has_key(builtin_method): - print "no regression test case for method '"+builtin_method+"'" +# Check every path through every method of UserDict + +from UserDict import UserDict + +d0 = {} +d1 = {"one": 1} +d2 = {"one": 1, "two": 2} + +# Test constructors + +u = UserDict() +u0 = UserDict(d0) +u1 = UserDict(d1) +u2 = UserDict(d2) + +uu = UserDict(u) +uu0 = UserDict(u0) +uu1 = UserDict(u1) +uu2 = UserDict(u2) + +# Test __repr__ + +assert str(u0) == str(d0) +assert repr(u1) == repr(d1) +assert `u2` == `d2` + +# Test __cmp__ and __len__ + +all = [d0, d1, d2, u, u0, u1, u2, uu, uu0, uu1, uu2] +for a in all: + for b in all: + assert cmp(a, b) == cmp(len(a), len(b)) + +# Test __getitem__ + +assert u2["one"] == 1 +try: + u1["two"] +except KeyError: + pass +else: + assert 0, "u1['two'] shouldn't exist" + +# Test __setitem__ + +u3 = UserDict(u2) +u3["two"] = 2 +u3["three"] = 3 + +# Test __delitem__ + +del u3["three"] +try: + del u3["three"] +except KeyError: + pass +else: + assert 0, "u3['three'] shouldn't exist" + +# Test clear + +u3.clear() +assert u3 == {} + +# Test copy() + +u2a = u2.copy() +assert u2a == u2 + +class MyUserDict(UserDict): + def display(self): print self + +m2 = MyUserDict(u2) +m2a = m2.copy() +assert m2a == m2 + +# Test keys, items, values + +assert u2.keys() == d2.keys() +assert u2.items() == d2.items() +assert u2.values() == d2.values() + +# Test has_key + +for i in u2.keys(): + assert u2.has_key(i) == 1 + assert u1.has_key(i) == d1.has_key(i) + assert u0.has_key(i) == d0.has_key(i) + +# Test update + +t = UserDict() +t.update(u2) +assert t == u2 + +# Test get + +for i in u2.keys(): + assert u2.get(i) == u2[i] + assert u1.get(i) == d1.get(i) + assert u0.get(i) == d0.get(i) diff --git a/Lib/dos-8x3/threadin.py b/Lib/dos-8x3/threadin.py index fb2eb21..4921f0e 100644 --- a/Lib/dos-8x3/threadin.py +++ b/Lib/dos-8x3/threadin.py @@ -462,11 +462,8 @@ class _MainThread(Thread): _active_limbo_lock.acquire() _active[_get_ident()] = self _active_limbo_lock.release() - try: - self.__oldexitfunc = _sys.exitfunc - except AttributeError: - self.__oldexitfunc = None - _sys.exitfunc = self.__exitfunc + import atexit + atexit.register(self.__exitfunc) def _set_daemon(self): return 0 @@ -480,10 +477,6 @@ class _MainThread(Thread): while t: t.join() t = _pickSomeNonDaemonThread() - if self.__oldexitfunc: - if __debug__: - self._note("%s: calling exit handler", self) - self.__oldexitfunc() if __debug__: self._note("%s: exiting", self) self._Thread__delete() diff --git a/Lib/dos-8x3/tracebac.py b/Lib/dos-8x3/tracebac.py index d219340..b733598 100755 --- a/Lib/dos-8x3/tracebac.py +++ b/Lib/dos-8x3/tracebac.py @@ -166,9 +166,15 @@ def format_exception_only(etype, value): s = s + ' ' list.append('%s^\n' % s) value = msg - list.append('%s: %s\n' % (str(stype), str(value))) + list.append('%s: %s\n' % (str(stype), _some_str(value))) return list +def _some_str(value): + try: + return str(value) + except: + return '<unprintable %s object>' % type(value).__name__ + def print_exc(limit=None, file=None): """This is a shorthand for 'print_exception(sys.exc_type, diff --git a/Lib/dos-8x3/userdict.py b/Lib/dos-8x3/userdict.py index 3c48415..9b6e73b 100755 --- a/Lib/dos-8x3/userdict.py +++ b/Lib/dos-8x3/userdict.py @@ -34,3 +34,7 @@ class UserDict: self.data[k] = v def get(self, key, failobj=None): return self.data.get(key, failobj) + def setdefault(self, key, failobj=None): + if not self.data.has_key(key): + self.data[key] = failobj + return self.data[key] diff --git a/Lib/dos-8x3/userlist.py b/Lib/dos-8x3/userlist.py index d4a8d2f..1146060 100755 --- a/Lib/dos-8x3/userlist.py +++ b/Lib/dos-8x3/userlist.py @@ -51,9 +51,20 @@ class UserList: return self.__class__(other + self.data) else: return self.__class__(list(other) + self.data) + def __iadd__(self, other): + if isinstance(other, UserList): + self.data += other.data + elif isinstance(other, type(self.data)): + self.data += other + else: + self.data += list(other) + return self def __mul__(self, n): return self.__class__(self.data*n) __rmul__ = __mul__ + def __imul__(self, n): + self.data *= n + return self def append(self, item): self.data.append(item) def insert(self, i, item): self.data.insert(i, item) def pop(self, i=-1): return self.data.pop(i) diff --git a/Lib/dos-8x3/userstri.py b/Lib/dos-8x3/userstri.py index 528065e..ea3d515 100644 --- a/Lib/dos-8x3/userstri.py +++ b/Lib/dos-8x3/userstri.py @@ -50,9 +50,20 @@ class UserString: return self.__class__(other + self.data) else: return self.__class__(str(other) + self.data) + def __iadd__(self, other): + if isinstance(other, UserString): + self.data += other.data + elif isinstance(other, StringType) or isinstance(other, UnicodeType): + self.data += other + else: + self.data += str(other) + return self def __mul__(self, n): return self.__class__(self.data*n) __rmul__ = __mul__ + def __imull__(self, n): + self.data += n + return self # the following methods are defined in alphabetical order: def capitalize(self): return self.__class__(self.data.capitalize()) @@ -75,6 +86,8 @@ class UserString: return self.data.find(sub, start, end) def index(self, sub, start=0, end=sys.maxint): return self.data.index(sub, start, end) + def isalpha(self): return self.data.isalpha() + def isalnum(self): return self.data.isalnum() def isdecimal(self): return self.data.isdecimal() def isdigit(self): return self.data.isdigit() def islower(self): return self.data.islower() @@ -102,8 +115,8 @@ class UserString: def strip(self): return self.__class__(self.data.strip()) def swapcase(self): return self.__class__(self.data.swapcase()) def title(self): return self.__class__(self.data.title()) - def translate(self, table, deletechars=""): - return self.__class__(self.data.translate(table, deletechars)) + def translate(self, *args): + return self.__class__(self.data.translate(*args)) def upper(self): return self.__class__(self.data.upper()) class MutableString(UserString): |