Mass patch by Ka-Ping Yee:

1. Comments at the beginning of the module, before
       functions, and before classes have been turned
       into docstrings.

    2. Tabs are normalized to four spaces.

Also, removed the "remove" function from dircmp.py, which reimplements
list.remove() (it must have been very old).
This commit is contained in:
Guido van Rossum 2000-02-02 15:10:15 +00:00
parent 113e70efa2
commit 4acc25bd39
18 changed files with 2513 additions and 2515 deletions

View File

@ -1,4 +1,4 @@
# A multi-producer, multi-consumer queue. """A multi-producer, multi-consumer queue."""
# define this exception to be compatible with Python 1.5's class # define this exception to be compatible with Python 1.5's class
# exceptions, but also when -X option is used. # exceptions, but also when -X option is used.

View File

@ -1,30 +1,30 @@
# class StringIO implements file-like objects that read/write a """File-like objects that read from or write to a string buffer.
# string buffer (a.k.a. "memory files").
# This implements (nearly) all stdio methods.
# This implements (nearly) all stdio methods.
# f = StringIO() # ready for writing
# f = StringIO() # ready for writing f = StringIO(buf) # ready for reading
# f = StringIO(buf) # ready for reading f.close() # explicitly release resources held
# f.close() # explicitly release resources held flag = f.isatty() # always false
# flag = f.isatty() # always false pos = f.tell() # get current position
# pos = f.tell() # get current position f.seek(pos) # set current position
# f.seek(pos) # set current position f.seek(pos, mode) # mode 0: absolute; 1: relative; 2: relative to EOF
# f.seek(pos, mode) # mode 0: absolute; 1: relative; 2: relative to EOF buf = f.read() # read until EOF
# buf = f.read() # read until EOF buf = f.read(n) # read up to n bytes
# buf = f.read(n) # read up to n bytes buf = f.readline() # read until end of line ('\n') or EOF
# buf = f.readline() # read until end of line ('\n') or EOF list = f.readlines()# list of f.readline() results until EOF
# list = f.readlines()# list of f.readline() results until EOF f.write(buf) # write at current position
# f.write(buf) # write at current position f.writelines(list) # for line in list: f.write(line)
# f.writelines(list) # for line in list: f.write(line) f.getvalue() # return whole file's contents as a string
# f.getvalue() # return whole file's contents as a string
# Notes:
# Notes: - Using a real file is often faster (but less convenient).
# - Using a real file is often faster (but less convenient). - fileno() is left unimplemented so that code which uses it triggers
# - fileno() is left unimplemented so that code which uses it triggers an exception early.
# an exception early. - Seeking far beyond EOF and then writing will insert real null
# - Seeking far beyond EOF and then writing will insert real null bytes that occupy space in the buffer.
# bytes that occupy space in the buffer. - There's a simple test set (see end of this file).
# - There's a simple test set (see end of this file). """
import string import string

View File

@ -1,4 +1,4 @@
# A more or less complete user-defined wrapper around dictionary objects """A more or less complete user-defined wrapper around dictionary objects."""
class UserDict: class UserDict:
def __init__(self, dict=None): def __init__(self, dict=None):

View File

@ -1,4 +1,4 @@
# A more or less complete user-defined wrapper around list objects """A more or less complete user-defined wrapper around list objects."""
class UserList: class UserList:
def __init__(self, list=None): def __init__(self, list=None):

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,5 @@
"""Classes for manipulating audio devices (currently only for Sun and SGI)"""
error = 'audiodev.error' error = 'audiodev.error'
class Play_Audio_sgi: class Play_Audio_sgi:

View File

@ -1,7 +1,7 @@
#! /usr/bin/env python #! /usr/bin/env python
# Conversions to/from base64 transport encoding as per RFC-1521. """Conversions to/from base64 transport encoding as per RFC-1521."""
#
# Modified 04-Oct-95 by Jack to use binascii module # Modified 04-Oct-95 by Jack to use binascii module
import binascii import binascii
@ -9,69 +9,71 @@ import binascii
MAXLINESIZE = 76 # Excluding the CRLF MAXLINESIZE = 76 # Excluding the CRLF
MAXBINSIZE = (MAXLINESIZE/4)*3 MAXBINSIZE = (MAXLINESIZE/4)*3
# Encode a file.
def encode(input, output): def encode(input, output):
while 1: """Encode a file."""
s = input.read(MAXBINSIZE) while 1:
if not s: break s = input.read(MAXBINSIZE)
while len(s) < MAXBINSIZE: if not s: break
ns = input.read(MAXBINSIZE-len(s)) while len(s) < MAXBINSIZE:
if not ns: break ns = input.read(MAXBINSIZE-len(s))
s = s + ns if not ns: break
line = binascii.b2a_base64(s) s = s + ns
output.write(line) line = binascii.b2a_base64(s)
output.write(line)
# Decode a file.
def decode(input, output): def decode(input, output):
while 1: """Decode a file."""
line = input.readline() while 1:
if not line: break line = input.readline()
s = binascii.a2b_base64(line) if not line: break
output.write(s) s = binascii.a2b_base64(line)
output.write(s)
def encodestring(s): def encodestring(s):
import StringIO """Encode a string."""
f = StringIO.StringIO(s) import StringIO
g = StringIO.StringIO() f = StringIO.StringIO(s)
encode(f, g) g = StringIO.StringIO()
return g.getvalue() encode(f, g)
return g.getvalue()
def decodestring(s): def decodestring(s):
import StringIO """Decode a string."""
f = StringIO.StringIO(s) import StringIO
g = StringIO.StringIO() f = StringIO.StringIO(s)
decode(f, g) g = StringIO.StringIO()
return g.getvalue() decode(f, g)
return g.getvalue()
# Small test program
def test(): def test():
import sys, getopt """Small test program"""
try: import sys, getopt
opts, args = getopt.getopt(sys.argv[1:], 'deut') try:
except getopt.error, msg: opts, args = getopt.getopt(sys.argv[1:], 'deut')
sys.stdout = sys.stderr except getopt.error, msg:
print msg sys.stdout = sys.stderr
print """usage: basd64 [-d] [-e] [-u] [-t] [file|-] print msg
-d, -u: decode print """usage: basd64 [-d] [-e] [-u] [-t] [file|-]
-e: encode (default) -d, -u: decode
-t: decode string 'Aladdin:open sesame'""" -e: encode (default)
sys.exit(2) -t: decode string 'Aladdin:open sesame'"""
func = encode sys.exit(2)
for o, a in opts: func = encode
if o == '-e': func = encode for o, a in opts:
if o == '-d': func = decode if o == '-e': func = encode
if o == '-u': func = decode if o == '-d': func = decode
if o == '-t': test1(); return if o == '-u': func = decode
if args and args[0] != '-': if o == '-t': test1(); return
func(open(args[0], 'rb'), sys.stdout) if args and args[0] != '-':
else: func(open(args[0], 'rb'), sys.stdout)
func(sys.stdin, sys.stdout) else:
func(sys.stdin, sys.stdout)
def test1(): def test1():
s0 = "Aladdin:open sesame" s0 = "Aladdin:open sesame"
s1 = encodestring(s0) s1 = encodestring(s0)
s2 = decodestring(s1) s2 = decodestring(s1)
print s0, `s1`, s2 print s0, `s1`, s2
if __name__ == '__main__': if __name__ == '__main__':
test() test()

1008
Lib/bdb.py

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,5 @@
"""binhex - Macintosh binhex compression/decompression """binhex - Macintosh binhex compression/decompression
easy interface: easy interface:
binhex(inputfilename, outputfilename) binhex(inputfilename, outputfilename)
hexbin(inputfilename, outputfilename) hexbin(inputfilename, outputfilename)
@ -25,16 +26,16 @@ import os
import struct import struct
import string import string
import binascii import binascii
Error = 'binhex.Error' Error = 'binhex.Error'
# States (what have we written) # States (what have we written)
[_DID_HEADER, _DID_DATA, _DID_RSRC] = range(3) [_DID_HEADER, _DID_DATA, _DID_RSRC] = range(3)
# Various constants # Various constants
REASONABLY_LARGE=32768 # Minimal amount we pass the rle-coder REASONABLY_LARGE=32768 # Minimal amount we pass the rle-coder
LINELEN=64 LINELEN=64
RUNCHAR=chr(0x90) # run-length introducer RUNCHAR=chr(0x90) # run-length introducer
# #
# This code is no longer byte-order dependent # This code is no longer byte-order dependent
@ -42,488 +43,488 @@ RUNCHAR=chr(0x90) # run-length introducer
# #
# Workarounds for non-mac machines. # Workarounds for non-mac machines.
if os.name == 'mac': if os.name == 'mac':
import macfs import macfs
import MacOS import MacOS
try: try:
openrf = MacOS.openrf openrf = MacOS.openrf
except AttributeError: except AttributeError:
# Backward compatability # Backward compatability
openrf = open openrf = open
def FInfo(): def FInfo():
return macfs.FInfo() return macfs.FInfo()
def getfileinfo(name): def getfileinfo(name):
finfo = macfs.FSSpec(name).GetFInfo() finfo = macfs.FSSpec(name).GetFInfo()
dir, file = os.path.split(name) dir, file = os.path.split(name)
# XXXX Get resource/data sizes # XXXX Get resource/data sizes
fp = open(name, 'rb') fp = open(name, 'rb')
fp.seek(0, 2) fp.seek(0, 2)
dlen = fp.tell() dlen = fp.tell()
fp = openrf(name, '*rb') fp = openrf(name, '*rb')
fp.seek(0, 2) fp.seek(0, 2)
rlen = fp.tell() rlen = fp.tell()
return file, finfo, dlen, rlen return file, finfo, dlen, rlen
def openrsrc(name, *mode): def openrsrc(name, *mode):
if not mode: if not mode:
mode = '*rb' mode = '*rb'
else: else:
mode = '*' + mode[0] mode = '*' + mode[0]
return openrf(name, mode) return openrf(name, mode)
else: else:
# #
# Glue code for non-macintosh useage # Glue code for non-macintosh useage
# #
class FInfo: class FInfo:
def __init__(self): def __init__(self):
self.Type = '????' self.Type = '????'
self.Creator = '????' self.Creator = '????'
self.Flags = 0 self.Flags = 0
def getfileinfo(name): def getfileinfo(name):
finfo = FInfo() finfo = FInfo()
# Quick check for textfile # Quick check for textfile
fp = open(name) fp = open(name)
data = open(name).read(256) data = open(name).read(256)
for c in data: for c in data:
if not c in string.whitespace \ if not c in string.whitespace \
and (c<' ' or ord(c) > 0177): and (c<' ' or ord(c) > 0177):
break break
else: else:
finfo.Type = 'TEXT' finfo.Type = 'TEXT'
fp.seek(0, 2) fp.seek(0, 2)
dsize = fp.tell() dsize = fp.tell()
fp.close() fp.close()
dir, file = os.path.split(name) dir, file = os.path.split(name)
file = string.replace(file, ':', '-', 1) file = string.replace(file, ':', '-', 1)
return file, finfo, dsize, 0 return file, finfo, dsize, 0
class openrsrc: class openrsrc:
def __init__(self, *args): def __init__(self, *args):
pass pass
def read(self, *args): def read(self, *args):
return '' return ''
def write(self, *args): def write(self, *args):
pass pass
def close(self): def close(self):
pass pass
class _Hqxcoderengine: class _Hqxcoderengine:
"""Write data to the coder in 3-byte chunks""" """Write data to the coder in 3-byte chunks"""
def __init__(self, ofp): def __init__(self, ofp):
self.ofp = ofp self.ofp = ofp
self.data = '' self.data = ''
self.hqxdata = '' self.hqxdata = ''
self.linelen = LINELEN-1 self.linelen = LINELEN-1
def write(self, data): def write(self, data):
self.data = self.data + data self.data = self.data + data
datalen = len(self.data) datalen = len(self.data)
todo = (datalen/3)*3 todo = (datalen/3)*3
data = self.data[:todo] data = self.data[:todo]
self.data = self.data[todo:] self.data = self.data[todo:]
if not data: if not data:
return return
self.hqxdata = self.hqxdata + binascii.b2a_hqx(data) self.hqxdata = self.hqxdata + binascii.b2a_hqx(data)
self._flush(0) self._flush(0)
def _flush(self, force): def _flush(self, force):
first = 0 first = 0
while first <= len(self.hqxdata)-self.linelen: while first <= len(self.hqxdata)-self.linelen:
last = first + self.linelen last = first + self.linelen
self.ofp.write(self.hqxdata[first:last]+'\n') self.ofp.write(self.hqxdata[first:last]+'\n')
self.linelen = LINELEN self.linelen = LINELEN
first = last first = last
self.hqxdata = self.hqxdata[first:] self.hqxdata = self.hqxdata[first:]
if force: if force:
self.ofp.write(self.hqxdata + ':\n') self.ofp.write(self.hqxdata + ':\n')
def close(self): def close(self):
if self.data: if self.data:
self.hqxdata = \ self.hqxdata = \
self.hqxdata + binascii.b2a_hqx(self.data) self.hqxdata + binascii.b2a_hqx(self.data)
self._flush(1) self._flush(1)
self.ofp.close() self.ofp.close()
del self.ofp del self.ofp
class _Rlecoderengine: class _Rlecoderengine:
"""Write data to the RLE-coder in suitably large chunks""" """Write data to the RLE-coder in suitably large chunks"""
def __init__(self, ofp): def __init__(self, ofp):
self.ofp = ofp self.ofp = ofp
self.data = '' self.data = ''
def write(self, data): def write(self, data):
self.data = self.data + data self.data = self.data + data
if len(self.data) < REASONABLY_LARGE: if len(self.data) < REASONABLY_LARGE:
return return
rledata = binascii.rlecode_hqx(self.data) rledata = binascii.rlecode_hqx(self.data)
self.ofp.write(rledata) self.ofp.write(rledata)
self.data = '' self.data = ''
def close(self): def close(self):
if self.data: if self.data:
rledata = binascii.rlecode_hqx(self.data) rledata = binascii.rlecode_hqx(self.data)
self.ofp.write(rledata) self.ofp.write(rledata)
self.ofp.close() self.ofp.close()
del self.ofp del self.ofp
class BinHex: class BinHex:
def __init__(self, (name, finfo, dlen, rlen), ofp): def __init__(self, (name, finfo, dlen, rlen), ofp):
if type(ofp) == type(''): if type(ofp) == type(''):
ofname = ofp ofname = ofp
ofp = open(ofname, 'w') ofp = open(ofname, 'w')
if os.name == 'mac': if os.name == 'mac':
fss = macfs.FSSpec(ofname) fss = macfs.FSSpec(ofname)
fss.SetCreatorType('BnHq', 'TEXT') fss.SetCreatorType('BnHq', 'TEXT')
ofp.write('(This file must be converted with BinHex 4.0)\n\n:') ofp.write('(This file must be converted with BinHex 4.0)\n\n:')
hqxer = _Hqxcoderengine(ofp) hqxer = _Hqxcoderengine(ofp)
self.ofp = _Rlecoderengine(hqxer) self.ofp = _Rlecoderengine(hqxer)
self.crc = 0 self.crc = 0
if finfo == None: if finfo == None:
finfo = FInfo() finfo = FInfo()
self.dlen = dlen self.dlen = dlen
self.rlen = rlen self.rlen = rlen
self._writeinfo(name, finfo) self._writeinfo(name, finfo)
self.state = _DID_HEADER self.state = _DID_HEADER
def _writeinfo(self, name, finfo): def _writeinfo(self, name, finfo):
name = name name = name
nl = len(name) nl = len(name)
if nl > 63: if nl > 63:
raise Error, 'Filename too long' raise Error, 'Filename too long'
d = chr(nl) + name + '\0' d = chr(nl) + name + '\0'
d2 = finfo.Type + finfo.Creator d2 = finfo.Type + finfo.Creator
# Force all structs to be packed with big-endian # Force all structs to be packed with big-endian
d3 = struct.pack('>h', finfo.Flags) d3 = struct.pack('>h', finfo.Flags)
d4 = struct.pack('>ii', self.dlen, self.rlen) d4 = struct.pack('>ii', self.dlen, self.rlen)
info = d + d2 + d3 + d4 info = d + d2 + d3 + d4
self._write(info) self._write(info)
self._writecrc() self._writecrc()
def _write(self, data): def _write(self, data):
self.crc = binascii.crc_hqx(data, self.crc) self.crc = binascii.crc_hqx(data, self.crc)
self.ofp.write(data) self.ofp.write(data)
def _writecrc(self): def _writecrc(self):
# XXXX Should this be here?? # XXXX Should this be here??
# self.crc = binascii.crc_hqx('\0\0', self.crc) # self.crc = binascii.crc_hqx('\0\0', self.crc)
self.ofp.write(struct.pack('>h', self.crc)) self.ofp.write(struct.pack('>h', self.crc))
self.crc = 0 self.crc = 0
def write(self, data): def write(self, data):
if self.state != _DID_HEADER: if self.state != _DID_HEADER:
raise Error, 'Writing data at the wrong time' raise Error, 'Writing data at the wrong time'
self.dlen = self.dlen - len(data) self.dlen = self.dlen - len(data)
self._write(data) self._write(data)
def close_data(self): def close_data(self):
if self.dlen <> 0: if self.dlen <> 0:
raise Error, 'Incorrect data size, diff='+`self.rlen` raise Error, 'Incorrect data size, diff='+`self.rlen`
self._writecrc() self._writecrc()
self.state = _DID_DATA self.state = _DID_DATA
def write_rsrc(self, data): def write_rsrc(self, data):
if self.state < _DID_DATA: if self.state < _DID_DATA:
self.close_data() self.close_data()
if self.state != _DID_DATA: if self.state != _DID_DATA:
raise Error, 'Writing resource data at the wrong time' raise Error, 'Writing resource data at the wrong time'
self.rlen = self.rlen - len(data) self.rlen = self.rlen - len(data)
self._write(data) self._write(data)
def close(self): def close(self):
if self.state < _DID_DATA: if self.state < _DID_DATA:
self.close_data() self.close_data()
if self.state != _DID_DATA: if self.state != _DID_DATA:
raise Error, 'Close at the wrong time' raise Error, 'Close at the wrong time'
if self.rlen <> 0: if self.rlen <> 0:
raise Error, \ raise Error, \
"Incorrect resource-datasize, diff="+`self.rlen` "Incorrect resource-datasize, diff="+`self.rlen`
self._writecrc() self._writecrc()
self.ofp.close() self.ofp.close()
self.state = None self.state = None
del self.ofp del self.ofp
def binhex(inp, out): def binhex(inp, out):
"""(infilename, outfilename) - Create binhex-encoded copy of a file""" """(infilename, outfilename) - Create binhex-encoded copy of a file"""
finfo = getfileinfo(inp) finfo = getfileinfo(inp)
ofp = BinHex(finfo, out) ofp = BinHex(finfo, out)
ifp = open(inp, 'rb') ifp = open(inp, 'rb')
# XXXX Do textfile translation on non-mac systems # XXXX Do textfile translation on non-mac systems
while 1: while 1:
d = ifp.read(128000) d = ifp.read(128000)
if not d: break if not d: break
ofp.write(d) ofp.write(d)
ofp.close_data() ofp.close_data()
ifp.close() ifp.close()
ifp = openrsrc(inp, 'rb') ifp = openrsrc(inp, 'rb')
while 1: while 1:
d = ifp.read(128000) d = ifp.read(128000)
if not d: break if not d: break
ofp.write_rsrc(d) ofp.write_rsrc(d)
ofp.close() ofp.close()
ifp.close() ifp.close()
class _Hqxdecoderengine: class _Hqxdecoderengine:
"""Read data via the decoder in 4-byte chunks""" """Read data via the decoder in 4-byte chunks"""
def __init__(self, ifp): def __init__(self, ifp):
self.ifp = ifp self.ifp = ifp
self.eof = 0 self.eof = 0
def read(self, totalwtd): def read(self, totalwtd):
"""Read at least wtd bytes (or until EOF)""" """Read at least wtd bytes (or until EOF)"""
decdata = '' decdata = ''
wtd = totalwtd wtd = totalwtd
# #
# The loop here is convoluted, since we don't really now how # The loop here is convoluted, since we don't really now how
# much to decode: there may be newlines in the incoming data. # much to decode: there may be newlines in the incoming data.
while wtd > 0: while wtd > 0:
if self.eof: return decdata if self.eof: return decdata
wtd = ((wtd+2)/3)*4 wtd = ((wtd+2)/3)*4
data = self.ifp.read(wtd) data = self.ifp.read(wtd)
# #
# Next problem: there may not be a complete number of # Next problem: there may not be a complete number of
# bytes in what we pass to a2b. Solve by yet another # bytes in what we pass to a2b. Solve by yet another
# loop. # loop.
# #
while 1: while 1:
try: try:
decdatacur, self.eof = \ decdatacur, self.eof = \
binascii.a2b_hqx(data) binascii.a2b_hqx(data)
break break
except binascii.Incomplete: except binascii.Incomplete:
pass pass
newdata = self.ifp.read(1) newdata = self.ifp.read(1)
if not newdata: if not newdata:
raise Error, \ raise Error, \
'Premature EOF on binhex file' 'Premature EOF on binhex file'
data = data + newdata data = data + newdata
decdata = decdata + decdatacur decdata = decdata + decdatacur
wtd = totalwtd - len(decdata) wtd = totalwtd - len(decdata)
if not decdata and not self.eof: if not decdata and not self.eof:
raise Error, 'Premature EOF on binhex file' raise Error, 'Premature EOF on binhex file'
return decdata return decdata
def close(self): def close(self):
self.ifp.close() self.ifp.close()
class _Rledecoderengine: class _Rledecoderengine:
"""Read data via the RLE-coder""" """Read data via the RLE-coder"""
def __init__(self, ifp): def __init__(self, ifp):
self.ifp = ifp self.ifp = ifp
self.pre_buffer = '' self.pre_buffer = ''
self.post_buffer = '' self.post_buffer = ''
self.eof = 0 self.eof = 0
def read(self, wtd): def read(self, wtd):
if wtd > len(self.post_buffer): if wtd > len(self.post_buffer):
self._fill(wtd-len(self.post_buffer)) self._fill(wtd-len(self.post_buffer))
rv = self.post_buffer[:wtd] rv = self.post_buffer[:wtd]
self.post_buffer = self.post_buffer[wtd:] self.post_buffer = self.post_buffer[wtd:]
return rv return rv
def _fill(self, wtd): def _fill(self, wtd):
self.pre_buffer = self.pre_buffer + self.ifp.read(wtd+4) self.pre_buffer = self.pre_buffer + self.ifp.read(wtd+4)
if self.ifp.eof: if self.ifp.eof:
self.post_buffer = self.post_buffer + \ self.post_buffer = self.post_buffer + \
binascii.rledecode_hqx(self.pre_buffer) binascii.rledecode_hqx(self.pre_buffer)
self.pre_buffer = '' self.pre_buffer = ''
return return
# #
# Obfuscated code ahead. We have to take care that we don't # Obfuscated code ahead. We have to take care that we don't
# end up with an orphaned RUNCHAR later on. So, we keep a couple # end up with an orphaned RUNCHAR later on. So, we keep a couple
# of bytes in the buffer, depending on what the end of # of bytes in the buffer, depending on what the end of
# the buffer looks like: # the buffer looks like:
# '\220\0\220' - Keep 3 bytes: repeated \220 (escaped as \220\0) # '\220\0\220' - Keep 3 bytes: repeated \220 (escaped as \220\0)
# '?\220' - Keep 2 bytes: repeated something-else # '?\220' - Keep 2 bytes: repeated something-else
# '\220\0' - Escaped \220: Keep 2 bytes. # '\220\0' - Escaped \220: Keep 2 bytes.
# '?\220?' - Complete repeat sequence: decode all # '?\220?' - Complete repeat sequence: decode all
# otherwise: keep 1 byte. # otherwise: keep 1 byte.
# #
mark = len(self.pre_buffer) mark = len(self.pre_buffer)
if self.pre_buffer[-3:] == RUNCHAR + '\0' + RUNCHAR: if self.pre_buffer[-3:] == RUNCHAR + '\0' + RUNCHAR:
mark = mark - 3 mark = mark - 3
elif self.pre_buffer[-1] == RUNCHAR: elif self.pre_buffer[-1] == RUNCHAR:
mark = mark - 2 mark = mark - 2
elif self.pre_buffer[-2:] == RUNCHAR + '\0': elif self.pre_buffer[-2:] == RUNCHAR + '\0':
mark = mark - 2 mark = mark - 2
elif self.pre_buffer[-2] == RUNCHAR: elif self.pre_buffer[-2] == RUNCHAR:
pass # Decode all pass # Decode all
else: else:
mark = mark - 1 mark = mark - 1
self.post_buffer = self.post_buffer + \ self.post_buffer = self.post_buffer + \
binascii.rledecode_hqx(self.pre_buffer[:mark]) binascii.rledecode_hqx(self.pre_buffer[:mark])
self.pre_buffer = self.pre_buffer[mark:] self.pre_buffer = self.pre_buffer[mark:]
def close(self): def close(self):
self.ifp.close() self.ifp.close()
class HexBin: class HexBin:
def __init__(self, ifp): def __init__(self, ifp):
if type(ifp) == type(''): if type(ifp) == type(''):
ifp = open(ifp) ifp = open(ifp)
# #
# Find initial colon. # Find initial colon.
# #
while 1: while 1:
ch = ifp.read(1) ch = ifp.read(1)
if not ch: if not ch:
raise Error, "No binhex data found" raise Error, "No binhex data found"
# Cater for \r\n terminated lines (which show up as \n\r, hence # Cater for \r\n terminated lines (which show up as \n\r, hence
# all lines start with \r) # all lines start with \r)
if ch == '\r': if ch == '\r':
continue continue
if ch == ':': if ch == ':':
break break
if ch != '\n': if ch != '\n':
dummy = ifp.readline() dummy = ifp.readline()
hqxifp = _Hqxdecoderengine(ifp) hqxifp = _Hqxdecoderengine(ifp)
self.ifp = _Rledecoderengine(hqxifp) self.ifp = _Rledecoderengine(hqxifp)
self.crc = 0 self.crc = 0
self._readheader() self._readheader()
def _read(self, len): def _read(self, len):
data = self.ifp.read(len) data = self.ifp.read(len)
self.crc = binascii.crc_hqx(data, self.crc) self.crc = binascii.crc_hqx(data, self.crc)
return data return data
def _checkcrc(self): def _checkcrc(self):
filecrc = struct.unpack('>h', self.ifp.read(2))[0] & 0xffff filecrc = struct.unpack('>h', self.ifp.read(2))[0] & 0xffff
#self.crc = binascii.crc_hqx('\0\0', self.crc) #self.crc = binascii.crc_hqx('\0\0', self.crc)
# XXXX Is this needed?? # XXXX Is this needed??
self.crc = self.crc & 0xffff self.crc = self.crc & 0xffff
if filecrc != self.crc: if filecrc != self.crc:
raise Error, 'CRC error, computed %x, read %x' \ raise Error, 'CRC error, computed %x, read %x' \
%(self.crc, filecrc) %(self.crc, filecrc)
self.crc = 0 self.crc = 0
def _readheader(self): def _readheader(self):
len = self._read(1) len = self._read(1)
fname = self._read(ord(len)) fname = self._read(ord(len))
rest = self._read(1+4+4+2+4+4) rest = self._read(1+4+4+2+4+4)
self._checkcrc() self._checkcrc()
type = rest[1:5] type = rest[1:5]
creator = rest[5:9] creator = rest[5:9]
flags = struct.unpack('>h', rest[9:11])[0] flags = struct.unpack('>h', rest[9:11])[0]
self.dlen = struct.unpack('>l', rest[11:15])[0] self.dlen = struct.unpack('>l', rest[11:15])[0]
self.rlen = struct.unpack('>l', rest[15:19])[0] self.rlen = struct.unpack('>l', rest[15:19])[0]
self.FName = fname self.FName = fname
self.FInfo = FInfo() self.FInfo = FInfo()
self.FInfo.Creator = creator self.FInfo.Creator = creator
self.FInfo.Type = type self.FInfo.Type = type
self.FInfo.Flags = flags self.FInfo.Flags = flags
self.state = _DID_HEADER self.state = _DID_HEADER
def read(self, *n): def read(self, *n):
if self.state != _DID_HEADER: if self.state != _DID_HEADER:
raise Error, 'Read data at wrong time' raise Error, 'Read data at wrong time'
if n: if n:
n = n[0] n = n[0]
n = min(n, self.dlen) n = min(n, self.dlen)
else: else:
n = self.dlen n = self.dlen
rv = '' rv = ''
while len(rv) < n: while len(rv) < n:
rv = rv + self._read(n-len(rv)) rv = rv + self._read(n-len(rv))
self.dlen = self.dlen - n self.dlen = self.dlen - n
return rv return rv
def close_data(self): def close_data(self):
if self.state != _DID_HEADER: if self.state != _DID_HEADER:
raise Error, 'close_data at wrong time' raise Error, 'close_data at wrong time'
if self.dlen: if self.dlen:
dummy = self._read(self.dlen) dummy = self._read(self.dlen)
self._checkcrc() self._checkcrc()
self.state = _DID_DATA self.state = _DID_DATA
def read_rsrc(self, *n): def read_rsrc(self, *n):
if self.state == _DID_HEADER: if self.state == _DID_HEADER:
self.close_data() self.close_data()
if self.state != _DID_DATA: if self.state != _DID_DATA:
raise Error, 'Read resource data at wrong time' raise Error, 'Read resource data at wrong time'
if n: if n:
n = n[0] n = n[0]
n = min(n, self.rlen) n = min(n, self.rlen)
else: else:
n = self.rlen n = self.rlen
self.rlen = self.rlen - n self.rlen = self.rlen - n
return self._read(n) return self._read(n)
def close(self): def close(self):
if self.rlen: if self.rlen:
dummy = self.read_rsrc(self.rlen) dummy = self.read_rsrc(self.rlen)
self._checkcrc() self._checkcrc()
self.state = _DID_RSRC self.state = _DID_RSRC
self.ifp.close() self.ifp.close()
def hexbin(inp, out): def hexbin(inp, out):
"""(infilename, outfilename) - Decode binhexed file""" """(infilename, outfilename) - Decode binhexed file"""
ifp = HexBin(inp) ifp = HexBin(inp)
finfo = ifp.FInfo finfo = ifp.FInfo
if not out: if not out:
out = ifp.FName out = ifp.FName
if os.name == 'mac': if os.name == 'mac':
ofss = macfs.FSSpec(out) ofss = macfs.FSSpec(out)
out = ofss.as_pathname() out = ofss.as_pathname()
ofp = open(out, 'wb') ofp = open(out, 'wb')
# XXXX Do translation on non-mac systems # XXXX Do translation on non-mac systems
while 1: while 1:
d = ifp.read(128000) d = ifp.read(128000)
if not d: break if not d: break
ofp.write(d) ofp.write(d)
ofp.close() ofp.close()
ifp.close_data() ifp.close_data()
d = ifp.read_rsrc(128000) d = ifp.read_rsrc(128000)
if d: if d:
ofp = openrsrc(out, 'wb') ofp = openrsrc(out, 'wb')
ofp.write(d) ofp.write(d)
while 1: while 1:
d = ifp.read_rsrc(128000) d = ifp.read_rsrc(128000)
if not d: break if not d: break
ofp.write(d) ofp.write(d)
ofp.close() ofp.close()
if os.name == 'mac': if os.name == 'mac':
nfinfo = ofss.GetFInfo() nfinfo = ofss.GetFInfo()
nfinfo.Creator = finfo.Creator nfinfo.Creator = finfo.Creator
nfinfo.Type = finfo.Type nfinfo.Type = finfo.Type
nfinfo.Flags = finfo.Flags nfinfo.Flags = finfo.Flags
ofss.SetFInfo(nfinfo) ofss.SetFInfo(nfinfo)
ifp.close() ifp.close()
def _test(): def _test():
if os.name == 'mac': if os.name == 'mac':
fss, ok = macfs.PromptGetFile('File to convert:') fss, ok = macfs.PromptGetFile('File to convert:')
if not ok: if not ok:
sys.exit(0) sys.exit(0)
fname = fss.as_pathname() fname = fss.as_pathname()
else: else:
fname = sys.argv[1] fname = sys.argv[1]
binhex(fname, fname+'.hqx') binhex(fname, fname+'.hqx')
hexbin(fname+'.hqx', fname+'.viahqx') hexbin(fname+'.hqx', fname+'.viahqx')
#hexbin(fname, fname+'.unpacked') #hexbin(fname, fname+'.unpacked')
sys.exit(1) sys.exit(1)
if __name__ == '__main__': if __name__ == '__main__':
_test() _test()

View File

@ -1,25 +1,23 @@
# Bisection algorithms """Bisection algorithms."""
# Insert item x in list a, and keep it sorted assuming a is sorted
def insort(a, x, lo=0, hi=None): def insort(a, x, lo=0, hi=None):
if hi is None: """Insert item x in list a, and keep it sorted assuming a is sorted."""
hi = len(a) if hi is None:
while lo < hi: hi = len(a)
mid = (lo+hi)/2 while lo < hi:
if x < a[mid]: hi = mid mid = (lo+hi)/2
else: lo = mid+1 if x < a[mid]: hi = mid
a.insert(lo, x) else: lo = mid+1
a.insert(lo, x)
# Find the index where to insert item x in list a, assuming a is sorted
def bisect(a, x, lo=0, hi=None): def bisect(a, x, lo=0, hi=None):
if hi is None: """Find the index where to insert item x in list a, assuming a is sorted."""
hi = len(a) if hi is None:
while lo < hi: hi = len(a)
mid = (lo+hi)/2 while lo < hi:
if x < a[mid]: hi = mid mid = (lo+hi)/2
else: lo = mid+1 if x < a[mid]: hi = mid
return lo else: lo = mid+1
return lo

View File

@ -1,6 +1,4 @@
############################### """Calendar printing functions"""
# Calendar printing functions #
###############################
# Revision 2: uses funtions from built-in time module # Revision 2: uses funtions from built-in time module
@ -22,149 +20,149 @@ February = 2
mdays = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] mdays = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
# Full and abbreviated names of weekdays # Full and abbreviated names of weekdays
day_name = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', \ day_name = ['Monday', 'Tuesday', 'Wednesday', 'Thursday',
'Friday', 'Saturday', 'Sunday'] 'Friday', 'Saturday', 'Sunday']
day_abbr = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] day_abbr = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
# Full and abbreviated names of months (1-based arrays!!!) # Full and abbreviated names of months (1-based arrays!!!)
month_name = ['', 'January', 'February', 'March', 'April', \ month_name = ['', 'January', 'February', 'March', 'April',
'May', 'June', 'July', 'August', \ 'May', 'June', 'July', 'August',
'September', 'October', 'November', 'December'] 'September', 'October', 'November', 'December']
month_abbr = [' ', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', \ month_abbr = [' ', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
# Return 1 for leap years, 0 for non-leap years
def isleap(year): def isleap(year):
return year % 4 == 0 and (year % 100 <> 0 or year % 400 == 0) """Return 1 for leap years, 0 for non-leap years."""
return year % 4 == 0 and (year % 100 <> 0 or year % 400 == 0)
# Return number of leap years in range [y1, y2)
# Assume y1 <= y2 and no funny (non-leap century) years
def leapdays(y1, y2): def leapdays(y1, y2):
return (y2+3)/4 - (y1+3)/4 """Return number of leap years in range [y1, y2).
Assume y1 <= y2 and no funny (non-leap century) years."""
return (y2+3)/4 - (y1+3)/4
# Return weekday (0-6 ~ Mon-Sun) for year (1970-...), month (1-12), day (1-31)
def weekday(year, month, day): def weekday(year, month, day):
secs = mktime((year, month, day, 0, 0, 0, 0, 0, 0)) """Return weekday (0-6 ~ Mon-Sun) for year (1970-...), month (1-12), day (1-31)."""
tuple = localtime(secs) secs = mktime((year, month, day, 0, 0, 0, 0, 0, 0))
return tuple[6] tuple = localtime(secs)
return tuple[6]
# Return weekday (0-6 ~ Mon-Sun) and number of days (28-31) for year, month
def monthrange(year, month): def monthrange(year, month):
if not 1 <= month <= 12: raise ValueError, 'bad month number' """Return weekday (0-6 ~ Mon-Sun) and number of days (28-31) for year, month."""
day1 = weekday(year, month, 1) if not 1 <= month <= 12: raise ValueError, 'bad month number'
ndays = mdays[month] + (month == February and isleap(year)) day1 = weekday(year, month, 1)
return day1, ndays ndays = mdays[month] + (month == February and isleap(year))
return day1, ndays
# Return a matrix representing a month's calendar
# Each row represents a week; days outside this month are zero
def _monthcalendar(year, month): def _monthcalendar(year, month):
day1, ndays = monthrange(year, month) """Return a matrix representing a month's calendar.
rows = [] Each row represents a week; days outside this month are zero."""
r7 = range(7) day1, ndays = monthrange(year, month)
day = 1 - day1 rows = []
while day <= ndays: r7 = range(7)
row = [0, 0, 0, 0, 0, 0, 0] day = 1 - day1
for i in r7: while day <= ndays:
if 1 <= day <= ndays: row[i] = day row = [0, 0, 0, 0, 0, 0, 0]
day = day + 1 for i in r7:
rows.append(row) if 1 <= day <= ndays: row[i] = day
return rows day = day + 1
rows.append(row)
return rows
# Caching interface to _monthcalendar
_mc_cache = {} _mc_cache = {}
def monthcalendar(year, month): def monthcalendar(year, month):
key = (year, month) """Caching interface to _monthcalendar."""
if _mc_cache.has_key(key): key = (year, month)
return _mc_cache[key] if _mc_cache.has_key(key):
else: return _mc_cache[key]
_mc_cache[key] = ret = _monthcalendar(year, month) else:
return ret _mc_cache[key] = ret = _monthcalendar(year, month)
return ret
# Center a string in a field
def _center(str, width): def _center(str, width):
n = width - len(str) """Center a string in a field."""
if n <= 0: return str n = width - len(str)
return ' '*((n+1)/2) + str + ' '*((n)/2) if n <= 0: return str
return ' '*((n+1)/2) + str + ' '*((n)/2)
# XXX The following code knows that print separates items with space! # XXX The following code knows that print separates items with space!
# Print a single week (no newline)
def prweek(week, width): def prweek(week, width):
for day in week: """Print a single week (no newline)."""
if day == 0: s = '' for day in week:
else: s = `day` if day == 0: s = ''
print _center(s, width), else: s = `day`
print _center(s, width),
# Return a header for a week
def weekheader(width): def weekheader(width):
str = '' """Return a header for a week."""
if width >= 9: names = day_name str = ''
else: names = day_abbr if width >= 9: names = day_name
for i in range(7): else: names = day_abbr
if str: str = str + ' ' for i in range(7):
str = str + _center(names[i%7][:width], width) if str: str = str + ' '
return str str = str + _center(names[i%7][:width], width)
return str
# Print a month's calendar
def prmonth(year, month, w = 0, l = 0): def prmonth(year, month, w = 0, l = 0):
w = max(2, w) """Print a month's calendar."""
l = max(1, l) w = max(2, w)
print _center(month_name[month] + ' ' + `year`, 7*(w+1) - 1), l = max(1, l)
print '\n'*l, print _center(month_name[month] + ' ' + `year`, 7*(w+1) - 1),
print weekheader(w), print '\n'*l,
print '\n'*l, print weekheader(w),
for week in monthcalendar(year, month): print '\n'*l,
prweek(week, w) for week in monthcalendar(year, month):
print '\n'*l, prweek(week, w)
print '\n'*l,
# Spacing of month columns # Spacing of month columns
_colwidth = 7*3 - 1 # Amount printed by prweek() _colwidth = 7*3 - 1 # Amount printed by prweek()
_spacing = ' '*4 # Spaces between columns _spacing = ' '*4 # Spaces between columns
# 3-column formatting for year calendars
def format3c(a, b, c): def format3c(a, b, c):
print _center(a, _colwidth), """3-column formatting for year calendars"""
print _spacing, print _center(a, _colwidth),
print _center(b, _colwidth), print _spacing,
print _spacing, print _center(b, _colwidth),
print _center(c, _colwidth) print _spacing,
print _center(c, _colwidth)
# Print a year's calendar
def prcal(year): def prcal(year):
header = weekheader(2) """Print a year's calendar."""
format3c('', `year`, '') header = weekheader(2)
for q in range(January, January+12, 3): format3c('', `year`, '')
print for q in range(January, January+12, 3):
format3c(month_name[q], month_name[q+1], month_name[q+2]) print
format3c(header, header, header) format3c(month_name[q], month_name[q+1], month_name[q+2])
data = [] format3c(header, header, header)
height = 0 data = []
for month in range(q, q+3): height = 0
cal = monthcalendar(year, month) for month in range(q, q+3):
if len(cal) > height: height = len(cal) cal = monthcalendar(year, month)
data.append(cal) if len(cal) > height: height = len(cal)
for i in range(height): data.append(cal)
for cal in data: for i in range(height):
if i >= len(cal): for cal in data:
print ' '*_colwidth, if i >= len(cal):
else: print ' '*_colwidth,
prweek(cal[i], 2) else:
print _spacing, prweek(cal[i], 2)
print print _spacing,
print
# Unrelated but handy function to calculate Unix timestamp from GMT
EPOCH = 1970 EPOCH = 1970
def timegm(tuple): def timegm(tuple):
year, month, day, hour, minute, second = tuple[:6] """Unrelated but handy function to calculate Unix timestamp from GMT."""
assert year >= EPOCH year, month, day, hour, minute, second = tuple[:6]
assert 1 <= month <= 12 assert year >= EPOCH
days = 365*(year-EPOCH) + leapdays(EPOCH, year) assert 1 <= month <= 12
for i in range(1, month): days = 365*(year-EPOCH) + leapdays(EPOCH, year)
days = days + mdays[i] for i in range(1, month):
if month > 2 and isleap(year): days = days + mdays[i]
days = days + 1 if month > 2 and isleap(year):
days = days + day - 1 days = days + 1
hours = days*24 + hour days = days + day - 1
minutes = hours*60 + minute hours = days*24 + hour
seconds = minutes*60 + second minutes = hours*60 + minute
return seconds seconds = minutes*60 + second
return seconds

View File

@ -1,39 +1,39 @@
# A generic class to build line-oriented command interpreters """A generic class to build line-oriented command interpreters.
#
# Interpreters constructed with this class obey the following conventions: Interpreters constructed with this class obey the following conventions:
#
# 1. End of file on input is processed as the command 'EOF'. 1. End of file on input is processed as the command 'EOF'.
# 2. A command is parsed out of each line by collecting the prefix composed 2. A command is parsed out of each line by collecting the prefix composed
# of characters in the identchars member. of characters in the identchars member.
# 3. A command `foo' is dispatched to a method 'do_foo()'; the do_ method 3. A command `foo' is dispatched to a method 'do_foo()'; the do_ method
# is passed a single argument consisting of the remainder of the line. is passed a single argument consisting of the remainder of the line.
# 4. Typing an empty line repeats the last command. (Actually, it calls the 4. Typing an empty line repeats the last command. (Actually, it calls the
# method `emptyline', which may be overridden in a subclass.) method `emptyline', which may be overridden in a subclass.)
# 5. There is a predefined `help' method. Given an argument `topic', it 5. There is a predefined `help' method. Given an argument `topic', it
# calls the command `help_topic'. With no arguments, it lists all topics calls the command `help_topic'. With no arguments, it lists all topics
# with defined help_ functions, broken into up to three topics; documented with defined help_ functions, broken into up to three topics; documented
# commands, miscellaneous help topics, and undocumented commands. commands, miscellaneous help topics, and undocumented commands.
# 6. The command '?' is a synonym for `help'. The command '!' is a synonym 6. The command '?' is a synonym for `help'. The command '!' is a synonym
# for `shell', if a do_shell method exists. for `shell', if a do_shell method exists.
#
# The `default' method may be overridden to intercept commands for which there The `default' method may be overridden to intercept commands for which there
# is no do_ method. is no do_ method.
#
# The data member `self.ruler' sets the character used to draw separator lines The data member `self.ruler' sets the character used to draw separator lines
# in the help messages. If empty, no ruler line is drawn. It defaults to "=". in the help messages. If empty, no ruler line is drawn. It defaults to "=".
#
# If the value of `self.intro' is nonempty when the cmdloop method is called, If the value of `self.intro' is nonempty when the cmdloop method is called,
# it is printed out on interpreter startup. This value may be overridden it is printed out on interpreter startup. This value may be overridden
# via an optional argument to the cmdloop() method. via an optional argument to the cmdloop() method.
#
# The data members `self.doc_header', `self.misc_header', and The data members `self.doc_header', `self.misc_header', and
# `self.undoc_header' set the headers used for the help function's `self.undoc_header' set the headers used for the help function's
# listings of documented functions, miscellaneous topics, and undocumented listings of documented functions, miscellaneous topics, and undocumented
# functions respectively. functions respectively.
#
# These interpreters use raw_input; thus, if the readline module is loaded, These interpreters use raw_input; thus, if the readline module is loaded,
# they automatically support Emacs-like command history and editing features. they automatically support Emacs-like command history and editing features.
# """
import string import string
@ -41,147 +41,147 @@ PROMPT = '(Cmd) '
IDENTCHARS = string.letters + string.digits + '_' IDENTCHARS = string.letters + string.digits + '_'
class Cmd: class Cmd:
prompt = PROMPT prompt = PROMPT
identchars = IDENTCHARS identchars = IDENTCHARS
ruler = '=' ruler = '='
lastcmd = '' lastcmd = ''
cmdqueue = [] cmdqueue = []
intro = None intro = None
doc_leader = "" doc_leader = ""
doc_header = "Documented commands (type help <topic>):" doc_header = "Documented commands (type help <topic>):"
misc_header = "Miscellaneous help topics:" misc_header = "Miscellaneous help topics:"
undoc_header = "Undocumented commands:" undoc_header = "Undocumented commands:"
nohelp = "*** No help on %s" nohelp = "*** No help on %s"
def __init__(self): pass def __init__(self): pass
def cmdloop(self, intro=None): def cmdloop(self, intro=None):
self.preloop() self.preloop()
if intro != None: if intro != None:
self.intro = intro self.intro = intro
if self.intro: if self.intro:
print self.intro print self.intro
stop = None stop = None
while not stop: while not stop:
if self.cmdqueue: if self.cmdqueue:
line = self.cmdqueue[0] line = self.cmdqueue[0]
del self.cmdqueue[0] del self.cmdqueue[0]
else: else:
try: try:
line = raw_input(self.prompt) line = raw_input(self.prompt)
except EOFError: except EOFError:
line = 'EOF' line = 'EOF'
line = self.precmd(line) line = self.precmd(line)
stop = self.onecmd(line) stop = self.onecmd(line)
stop = self.postcmd(stop, line) stop = self.postcmd(stop, line)
self.postloop() self.postloop()
def precmd(self, line): def precmd(self, line):
return line return line
def postcmd(self, stop, line): def postcmd(self, stop, line):
return stop return stop
def preloop(self): def preloop(self):
pass pass
def postloop(self): def postloop(self):
pass pass
def onecmd(self, line): def onecmd(self, line):
line = string.strip(line) line = string.strip(line)
if line == '?': if line == '?':
line = 'help' line = 'help'
elif line == '!': elif line == '!':
if hasattr(self, 'do_shell'): if hasattr(self, 'do_shell'):
line = 'shell' line = 'shell'
else: else:
return self.default(line) return self.default(line)
elif not line: elif not line:
return self.emptyline() return self.emptyline()
self.lastcmd = line self.lastcmd = line
i, n = 0, len(line) i, n = 0, len(line)
while i < n and line[i] in self.identchars: i = i+1 while i < n and line[i] in self.identchars: i = i+1
cmd, arg = line[:i], string.strip(line[i:]) cmd, arg = line[:i], string.strip(line[i:])
if cmd == '': if cmd == '':
return self.default(line) return self.default(line)
else: else:
try: try:
func = getattr(self, 'do_' + cmd) func = getattr(self, 'do_' + cmd)
except AttributeError: except AttributeError:
return self.default(line) return self.default(line)
return func(arg) return func(arg)
def emptyline(self): def emptyline(self):
if self.lastcmd: if self.lastcmd:
return self.onecmd(self.lastcmd) return self.onecmd(self.lastcmd)
def default(self, line): def default(self, line):
print '*** Unknown syntax:', line print '*** Unknown syntax:', line
def do_help(self, arg): def do_help(self, arg):
if arg: if arg:
# XXX check arg syntax # XXX check arg syntax
try: try:
func = getattr(self, 'help_' + arg) func = getattr(self, 'help_' + arg)
except: except:
try: try:
doc=getattr(self, 'do_' + arg).__doc__ doc=getattr(self, 'do_' + arg).__doc__
if doc: if doc:
print doc print doc
return return
except: except:
pass pass
print self.nohelp % (arg,) print self.nohelp % (arg,)
return return
func() func()
else: else:
# Inheritance says we have to look in class and # Inheritance says we have to look in class and
# base classes; order is not important. # base classes; order is not important.
names = [] names = []
classes = [self.__class__] classes = [self.__class__]
while classes: while classes:
aclass = classes[0] aclass = classes[0]
if aclass.__bases__: if aclass.__bases__:
classes = classes + list(aclass.__bases__) classes = classes + list(aclass.__bases__)
names = names + dir(aclass) names = names + dir(aclass)
del classes[0] del classes[0]
cmds_doc = [] cmds_doc = []
cmds_undoc = [] cmds_undoc = []
help = {} help = {}
for name in names: for name in names:
if name[:5] == 'help_': if name[:5] == 'help_':
help[name[5:]]=1 help[name[5:]]=1
names.sort() names.sort()
# There can be duplicates if routines overridden # There can be duplicates if routines overridden
prevname = '' prevname = ''
for name in names: for name in names:
if name[:3] == 'do_': if name[:3] == 'do_':
if name == prevname: if name == prevname:
continue continue
prevname = name prevname = name
cmd=name[3:] cmd=name[3:]
if help.has_key(cmd): if help.has_key(cmd):
cmds_doc.append(cmd) cmds_doc.append(cmd)
del help[cmd] del help[cmd]
elif getattr(self, name).__doc__: elif getattr(self, name).__doc__:
cmds_doc.append(cmd) cmds_doc.append(cmd)
else: else:
cmds_undoc.append(cmd) cmds_undoc.append(cmd)
print self.doc_leader print self.doc_leader
self.print_topics(self.doc_header, cmds_doc, 15,80) self.print_topics(self.doc_header, cmds_doc, 15,80)
self.print_topics(self.misc_header, help.keys(),15,80) self.print_topics(self.misc_header, help.keys(),15,80)
self.print_topics(self.undoc_header, cmds_undoc, 15,80) self.print_topics(self.undoc_header, cmds_undoc, 15,80)
def print_topics(self, header, cmds, cmdlen, maxcol): def print_topics(self, header, cmds, cmdlen, maxcol):
if cmds: if cmds:
print header; print header;
if self.ruler: if self.ruler:
print self.ruler * len(header) print self.ruler * len(header)
(cmds_per_line,junk)=divmod(maxcol,cmdlen) (cmds_per_line,junk)=divmod(maxcol,cmdlen)
col=cmds_per_line col=cmds_per_line
for cmd in cmds: for cmd in cmds:
if col==0: print if col==0: print
print (("%-"+`cmdlen`+"s") % cmd), print (("%-"+`cmdlen`+"s") % cmd),
col = (col+1) % cmds_per_line col = (col+1) % cmds_per_line
print "\n" print "\n"

View File

@ -1,61 +1,63 @@
# Module 'cmp' """Efficiently compare files, boolean outcome only (equal / not equal).
# Efficiently compare files, boolean outcome only (equal / not equal). Tricks (used in this order):
- Files with identical type, size & mtime are assumed to be clones
# Tricks (used in this order): - Files with different type or size cannot be identical
# - Files with identical type, size & mtime are assumed to be clones - We keep a cache of outcomes of earlier comparisons
# - Files with different type or size cannot be identical - We don't fork a process to run 'cmp' but read the files ourselves
# - We keep a cache of outcomes of earlier comparisons """
# - We don't fork a process to run 'cmp' but read the files ourselves
import os import os
cache = {} cache = {}
def cmp(f1, f2, shallow=1): # Compare two files, use the cache if possible. def cmp(f1, f2, shallow=1):
# Return 1 for identical files, 0 for different. """Compare two files, use the cache if possible.
# Raise exceptions if either file could not be statted, read, etc. Return 1 for identical files, 0 for different.
s1, s2 = sig(os.stat(f1)), sig(os.stat(f2)) Raise exceptions if either file could not be statted, read, etc."""
if s1[0] <> 8 or s2[0] <> 8: s1, s2 = sig(os.stat(f1)), sig(os.stat(f2))
# Either is a not a plain file -- always report as different if s1[0] <> 8 or s2[0] <> 8:
return 0 # Either is a not a plain file -- always report as different
if shallow and s1 == s2: return 0
# type, size & mtime match -- report same if shallow and s1 == s2:
return 1 # type, size & mtime match -- report same
if s1[:2] <> s2[:2]: # Types or sizes differ, don't bother return 1
# types or sizes differ -- report different if s1[:2] <> s2[:2]: # Types or sizes differ, don't bother
return 0 # types or sizes differ -- report different
# same type and size -- look in the cache return 0
key = (f1, f2) # same type and size -- look in the cache
try: key = (f1, f2)
cs1, cs2, outcome = cache[key] try:
# cache hit cs1, cs2, outcome = cache[key]
if s1 == cs1 and s2 == cs2: # cache hit
# cached signatures match if s1 == cs1 and s2 == cs2:
return outcome # cached signatures match
# stale cached signature(s) return outcome
except KeyError: # stale cached signature(s)
# cache miss except KeyError:
pass # cache miss
# really compare pass
outcome = do_cmp(f1, f2) # really compare
cache[key] = s1, s2, outcome outcome = do_cmp(f1, f2)
return outcome cache[key] = s1, s2, outcome
return outcome
def sig(st): # Return signature (i.e., type, size, mtime) from raw stat data def sig(st):
# 0-5: st_mode, st_ino, st_dev, st_nlink, st_uid, st_gid """Return signature (i.e., type, size, mtime) from raw stat data
# 6-9: st_size, st_atime, st_mtime, st_ctime 0-5: st_mode, st_ino, st_dev, st_nlink, st_uid, st_gid
type = st[0] / 4096 6-9: st_size, st_atime, st_mtime, st_ctime"""
size = st[6] type = st[0] / 4096
mtime = st[8] size = st[6]
return type, size, mtime mtime = st[8]
return type, size, mtime
def do_cmp(f1, f2): # Compare two files, really def do_cmp(f1, f2):
bufsize = 8*1024 # Could be tuned """Compare two files, really."""
fp1 = open(f1, 'rb') bufsize = 8*1024 # Could be tuned
fp2 = open(f2, 'rb') fp1 = open(f1, 'rb')
while 1: fp2 = open(f2, 'rb')
b1 = fp1.read(bufsize) while 1:
b2 = fp2.read(bufsize) b1 = fp1.read(bufsize)
if b1 <> b2: return 0 b2 = fp2.read(bufsize)
if not b1: return 1 if b1 <> b2: return 0
if not b1: return 1

View File

@ -1,13 +1,12 @@
# Module 'cmpcache' """Efficiently compare files, boolean outcome only (equal / not equal).
#
# Efficiently compare files, boolean outcome only (equal / not equal). Tricks (used in this order):
# - Use the statcache module to avoid statting files more than once
# Tricks (used in this order): - Files with identical type, size & mtime are assumed to be clones
# - Use the statcache module to avoid statting files more than once - Files with different type or size cannot be identical
# - Files with identical type, size & mtime are assumed to be clones - We keep a cache of outcomes of earlier comparisons
# - Files with different type or size cannot be identical - We don't fork a process to run 'cmp' but read the files ourselves
# - We keep a cache of outcomes of earlier comparisons """
# - We don't fork a process to run 'cmp' but read the files ourselves
import os import os
from stat import * from stat import *
@ -19,50 +18,47 @@ import statcache
cache = {} cache = {}
# Compare two files, use the cache if possible.
# May raise os.error if a stat or open of either fails.
#
def cmp(f1, f2, shallow=1): def cmp(f1, f2, shallow=1):
# Return 1 for identical files, 0 for different. """Compare two files, use the cache if possible.
# Raise exceptions if either file could not be statted, read, etc. May raise os.error if a stat or open of either fails.
s1, s2 = sig(statcache.stat(f1)), sig(statcache.stat(f2)) Return 1 for identical files, 0 for different.
if not S_ISREG(s1[0]) or not S_ISREG(s2[0]): Raise exceptions if either file could not be statted, read, etc."""
# Either is a not a plain file -- always report as different s1, s2 = sig(statcache.stat(f1)), sig(statcache.stat(f2))
return 0 if not S_ISREG(s1[0]) or not S_ISREG(s2[0]):
if shallow and s1 == s2: # Either is a not a plain file -- always report as different
# type, size & mtime match -- report same return 0
return 1 if shallow and s1 == s2:
if s1[:2] <> s2[:2]: # Types or sizes differ, don't bother # type, size & mtime match -- report same
# types or sizes differ -- report different return 1
return 0 if s1[:2] <> s2[:2]: # Types or sizes differ, don't bother
# same type and size -- look in the cache # types or sizes differ -- report different
key = f1 + ' ' + f2 return 0
if cache.has_key(key): # same type and size -- look in the cache
cs1, cs2, outcome = cache[key] key = f1 + ' ' + f2
# cache hit if cache.has_key(key):
if s1 == cs1 and s2 == cs2: cs1, cs2, outcome = cache[key]
# cached signatures match # cache hit
return outcome if s1 == cs1 and s2 == cs2:
# stale cached signature(s) # cached signatures match
# really compare return outcome
outcome = do_cmp(f1, f2) # stale cached signature(s)
cache[key] = s1, s2, outcome # really compare
return outcome outcome = do_cmp(f1, f2)
cache[key] = s1, s2, outcome
return outcome
# Return signature (i.e., type, size, mtime) from raw stat data.
#
def sig(st): def sig(st):
return S_IFMT(st[ST_MODE]), st[ST_SIZE], st[ST_MTIME] """Return signature (i.e., type, size, mtime) from raw stat data."""
return S_IFMT(st[ST_MODE]), st[ST_SIZE], st[ST_MTIME]
# Compare two files, really.
#
def do_cmp(f1, f2): def do_cmp(f1, f2):
#print ' cmp', f1, f2 # XXX remove when debugged """Compare two files, really."""
bufsize = 8*1024 # Could be tuned #print ' cmp', f1, f2 # XXX remove when debugged
fp1 = open(f1, 'rb') bufsize = 8*1024 # Could be tuned
fp2 = open(f2, 'rb') fp1 = open(f1, 'rb')
while 1: fp2 = open(f2, 'rb')
b1 = fp1.read(bufsize) while 1:
b2 = fp2.read(bufsize) b1 = fp1.read(bufsize)
if b1 <> b2: return 0 b2 = fp2.read(bufsize)
if not b1: return 1 if b1 <> b2: return 0
if not b1: return 1

View File

@ -1,4 +1,4 @@
# Helper to provide extensibility for pickle/cPickle. """Helper to provide extensibility for pickle/cPickle."""
dispatch_table = {} dispatch_table = {}
safe_constructors = {} safe_constructors = {}

View File

@ -1,35 +1,35 @@
# Module 'dircache' """Return a sorted list of the files in a directory, using a cache
# to avoid reading the directory more often than necessary.
# Return a sorted list of the files in a directory, using a cache Also contains a subroutine to append slashes to directories."""
# to avoid reading the directory more often than necessary.
# Also contains a subroutine to append slashes to directories.
import os import os
cache = {} cache = {}
def listdir(path): # List directory contents, using cache def listdir(path):
try: """List directory contents, using cache."""
cached_mtime, list = cache[path] try:
del cache[path] cached_mtime, list = cache[path]
except KeyError: del cache[path]
cached_mtime, list = -1, [] except KeyError:
try: cached_mtime, list = -1, []
mtime = os.stat(path)[8] try:
except os.error: mtime = os.stat(path)[8]
return [] except os.error:
if mtime <> cached_mtime: return []
try: if mtime <> cached_mtime:
list = os.listdir(path) try:
except os.error: list = os.listdir(path)
return [] except os.error:
list.sort() return []
cache[path] = mtime, list list.sort()
return list cache[path] = mtime, list
return list
opendir = listdir # XXX backward compatibility opendir = listdir # XXX backward compatibility
def annotate(head, list): # Add '/' suffixes to directories def annotate(head, list):
for i in range(len(list)): """Add '/' suffixes to directories."""
if os.path.isdir(os.path.join(head, list[i])): for i in range(len(list)):
list[i] = list[i] + '/' if os.path.isdir(os.path.join(head, list[i])):
list[i] = list[i] + '/'

View File

@ -1,6 +1,4 @@
# Module 'dirmp' """A class to build directory diff tools on."""
#
# Defines a class to build directory diff tools on.
import os import os
@ -9,195 +7,195 @@ import cmpcache
import statcache import statcache
from stat import * from stat import *
# Directory comparison class.
#
class dircmp: class dircmp:
# """Directory comparison class."""
def new(self, a, b): # Initialize
self.a = a def new(self, a, b):
self.b = b """Initialize."""
# Properties that caller may change before calling self.run(): self.a = a
self.hide = [os.curdir, os.pardir] # Names never to be shown self.b = b
self.ignore = ['RCS', 'tags'] # Names ignored in comparison # Properties that caller may change before calling self.run():
# self.hide = [os.curdir, os.pardir] # Names never to be shown
return self self.ignore = ['RCS', 'tags'] # Names ignored in comparison
#
def run(self): # Compare everything except common subdirectories return self
self.a_list = filter(dircache.listdir(self.a), self.hide)
self.b_list = filter(dircache.listdir(self.b), self.hide) def run(self):
self.a_list.sort() """Compare everything except common subdirectories."""
self.b_list.sort() self.a_list = filter(dircache.listdir(self.a), self.hide)
self.phase1() self.b_list = filter(dircache.listdir(self.b), self.hide)
self.phase2() self.a_list.sort()
self.phase3() self.b_list.sort()
# self.phase1()
def phase1(self): # Compute common names self.phase2()
self.a_only = [] self.phase3()
self.common = []
for x in self.a_list: def phase1(self):
if x in self.b_list: """Compute common names."""
self.common.append(x) self.a_only = []
else: self.common = []
self.a_only.append(x) for x in self.a_list:
# if x in self.b_list:
self.b_only = [] self.common.append(x)
for x in self.b_list: else:
if x not in self.common: self.a_only.append(x)
self.b_only.append(x)
# self.b_only = []
def phase2(self): # Distinguish files, directories, funnies for x in self.b_list:
self.common_dirs = [] if x not in self.common:
self.common_files = [] self.b_only.append(x)
self.common_funny = []
# def phase2(self):
for x in self.common: """Distinguish files, directories, funnies."""
a_path = os.path.join(self.a, x) self.common_dirs = []
b_path = os.path.join(self.b, x) self.common_files = []
# self.common_funny = []
ok = 1
try: for x in self.common:
a_stat = statcache.stat(a_path) a_path = os.path.join(self.a, x)
except os.error, why: b_path = os.path.join(self.b, x)
# print 'Can\'t stat', a_path, ':', why[1]
ok = 0 ok = 1
try: try:
b_stat = statcache.stat(b_path) a_stat = statcache.stat(a_path)
except os.error, why: except os.error, why:
# print 'Can\'t stat', b_path, ':', why[1] # print 'Can\'t stat', a_path, ':', why[1]
ok = 0 ok = 0
# try:
if ok: b_stat = statcache.stat(b_path)
a_type = S_IFMT(a_stat[ST_MODE]) except os.error, why:
b_type = S_IFMT(b_stat[ST_MODE]) # print 'Can\'t stat', b_path, ':', why[1]
if a_type <> b_type: ok = 0
self.common_funny.append(x)
elif S_ISDIR(a_type): if ok:
self.common_dirs.append(x) a_type = S_IFMT(a_stat[ST_MODE])
elif S_ISREG(a_type): b_type = S_IFMT(b_stat[ST_MODE])
self.common_files.append(x) if a_type <> b_type:
else: self.common_funny.append(x)
self.common_funny.append(x) elif S_ISDIR(a_type):
else: self.common_dirs.append(x)
self.common_funny.append(x) elif S_ISREG(a_type):
# self.common_files.append(x)
def phase3(self): # Find out differences between common files else:
xx = cmpfiles(self.a, self.b, self.common_files) self.common_funny.append(x)
self.same_files, self.diff_files, self.funny_files = xx else:
# self.common_funny.append(x)
def phase4(self): # Find out differences between common subdirectories
# A new dircmp object is created for each common subdirectory, def phase3(self):
# these are stored in a dictionary indexed by filename. """Find out differences between common files."""
# The hide and ignore properties are inherited from the parent xx = cmpfiles(self.a, self.b, self.common_files)
self.subdirs = {} self.same_files, self.diff_files, self.funny_files = xx
for x in self.common_dirs:
a_x = os.path.join(self.a, x) def phase4(self):
b_x = os.path.join(self.b, x) """Find out differences between common subdirectories.
self.subdirs[x] = newdd = dircmp().new(a_x, b_x) A new dircmp object is created for each common subdirectory,
newdd.hide = self.hide these are stored in a dictionary indexed by filename.
newdd.ignore = self.ignore The hide and ignore properties are inherited from the parent."""
newdd.run() self.subdirs = {}
# for x in self.common_dirs:
def phase4_closure(self): # Recursively call phase4() on subdirectories a_x = os.path.join(self.a, x)
self.phase4() b_x = os.path.join(self.b, x)
for x in self.subdirs.keys(): self.subdirs[x] = newdd = dircmp().new(a_x, b_x)
self.subdirs[x].phase4_closure() newdd.hide = self.hide
# newdd.ignore = self.ignore
def report(self): # Print a report on the differences between a and b newdd.run()
# Assume that phases 1 to 3 have been executed
# Output format is purposely lousy def phase4_closure(self):
print 'diff', self.a, self.b """Recursively call phase4() on subdirectories."""
if self.a_only: self.phase4()
print 'Only in', self.a, ':', self.a_only for x in self.subdirs.keys():
if self.b_only: self.subdirs[x].phase4_closure()
print 'Only in', self.b, ':', self.b_only
if self.same_files: def report(self):
print 'Identical files :', self.same_files """Print a report on the differences between a and b."""
if self.diff_files: # Assume that phases 1 to 3 have been executed
print 'Differing files :', self.diff_files # Output format is purposely lousy
if self.funny_files: print 'diff', self.a, self.b
print 'Trouble with common files :', self.funny_files if self.a_only:
if self.common_dirs: print 'Only in', self.a, ':', self.a_only
print 'Common subdirectories :', self.common_dirs if self.b_only:
if self.common_funny: print 'Only in', self.b, ':', self.b_only
print 'Common funny cases :', self.common_funny if self.same_files:
# print 'Identical files :', self.same_files
def report_closure(self): # Print reports on self and on subdirs if self.diff_files:
# If phase 4 hasn't been done, no subdir reports are printed print 'Differing files :', self.diff_files
self.report() if self.funny_files:
try: print 'Trouble with common files :', self.funny_files
x = self.subdirs if self.common_dirs:
except AttributeError: print 'Common subdirectories :', self.common_dirs
return # No subdirectories computed if self.common_funny:
for x in self.subdirs.keys(): print 'Common funny cases :', self.common_funny
print
self.subdirs[x].report_closure() def report_closure(self):
# """Print reports on self and on subdirs.
def report_phase4_closure(self): # Report and do phase 4 recursively If phase 4 hasn't been done, no subdir reports are printed."""
self.report() self.report()
self.phase4() try:
for x in self.subdirs.keys(): x = self.subdirs
print except AttributeError:
self.subdirs[x].report_phase4_closure() return # No subdirectories computed
for x in self.subdirs.keys():
print
self.subdirs[x].report_closure()
def report_phase4_closure(self):
"""Report and do phase 4 recursively."""
self.report()
self.phase4()
for x in self.subdirs.keys():
print
self.subdirs[x].report_phase4_closure()
# Compare common files in two directories.
# Return:
# - files that compare equal
# - files that compare different
# - funny cases (can't stat etc.)
#
def cmpfiles(a, b, common): def cmpfiles(a, b, common):
res = ([], [], []) """Compare common files in two directories.
for x in common: Return:
res[cmp(os.path.join(a, x), os.path.join(b, x))].append(x) - files that compare equal
return res - files that compare different
- funny cases (can't stat etc.)"""
res = ([], [], [])
for x in common:
res[cmp(os.path.join(a, x), os.path.join(b, x))].append(x)
return res
# Compare two files.
# Return:
# 0 for equal
# 1 for different
# 2 for funny cases (can't stat, etc.)
#
def cmp(a, b): def cmp(a, b):
try: """Compare two files.
if cmpcache.cmp(a, b): return 0 Return:
return 1 0 for equal
except os.error: 1 for different
return 2 2 for funny cases (can't stat, etc.)"""
try:
if cmpcache.cmp(a, b): return 0
return 1
except os.error:
return 2
# Remove a list item.
# NB: This modifies the list argument.
#
def remove(list, item):
for i in range(len(list)):
if list[i] == item:
del list[i]
break
# Return a copy with items that occur in skip removed.
#
def filter(list, skip): def filter(list, skip):
result = [] """Return a copy with items that occur in skip removed."""
for item in list:
if item not in skip: result.append(item) result = []
return result for item in list:
if item not in skip: result.append(item)
return result
# Demonstration and testing.
#
def demo(): def demo():
import sys """Demonstration and testing."""
import getopt
options, args = getopt.getopt(sys.argv[1:], 'r')
if len(args) <> 2: raise getopt.error, 'need exactly two args'
dd = dircmp().new(args[0], args[1])
dd.run()
if ('-r', '') in options:
dd.report_phase4_closure()
else:
dd.report()
# demo() import sys
import getopt
options, args = getopt.getopt(sys.argv[1:], 'r')
if len(args) <> 2: raise getopt.error, 'need exactly two args'
dd = dircmp().new(args[0], args[1])
dd.run()
if ('-r', '') in options:
dd.report_phase4_closure()
else:
dd.report()
if __name__ == "__main__":
demo()

View File

@ -1,15 +1,15 @@
# General floating point formatting functions. """General floating point formatting functions.
# Functions: Functions:
# fix(x, digits_behind) fix(x, digits_behind)
# sci(x, digits_behind) sci(x, digits_behind)
# Each takes a number or a string and a number of digits as arguments. Each takes a number or a string and a number of digits as arguments.
# Parameters:
# x: number to be formatted; or a string resembling a number
# digits_behind: number of digits behind the decimal point
Parameters:
x: number to be formatted; or a string resembling a number
digits_behind: number of digits behind the decimal point
"""
import re import re