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:
parent
113e70efa2
commit
4acc25bd39
|
@ -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
|
||||
# exceptions, but also when -X option is used.
|
||||
|
|
|
@ -1,30 +1,30 @@
|
|||
# class StringIO implements file-like objects that read/write a
|
||||
# string buffer (a.k.a. "memory files").
|
||||
#
|
||||
# This implements (nearly) all stdio methods.
|
||||
#
|
||||
# f = StringIO() # ready for writing
|
||||
# f = StringIO(buf) # ready for reading
|
||||
# f.close() # explicitly release resources held
|
||||
# flag = f.isatty() # always false
|
||||
# pos = f.tell() # get current position
|
||||
# f.seek(pos) # set current position
|
||||
# f.seek(pos, mode) # mode 0: absolute; 1: relative; 2: relative to EOF
|
||||
# buf = f.read() # read until EOF
|
||||
# buf = f.read(n) # read up to n bytes
|
||||
# buf = f.readline() # read until end of line ('\n') or EOF
|
||||
# list = f.readlines()# list of f.readline() results until EOF
|
||||
# f.write(buf) # write at current position
|
||||
# f.writelines(list) # for line in list: f.write(line)
|
||||
# f.getvalue() # return whole file's contents as a string
|
||||
#
|
||||
# Notes:
|
||||
# - Using a real file is often faster (but less convenient).
|
||||
# - fileno() is left unimplemented so that code which uses it triggers
|
||||
# an exception early.
|
||||
# - Seeking far beyond EOF and then writing will insert real null
|
||||
# bytes that occupy space in the buffer.
|
||||
# - There's a simple test set (see end of this file).
|
||||
"""File-like objects that read from or write to a string buffer.
|
||||
|
||||
This implements (nearly) all stdio methods.
|
||||
|
||||
f = StringIO() # ready for writing
|
||||
f = StringIO(buf) # ready for reading
|
||||
f.close() # explicitly release resources held
|
||||
flag = f.isatty() # always false
|
||||
pos = f.tell() # get current position
|
||||
f.seek(pos) # set current position
|
||||
f.seek(pos, mode) # mode 0: absolute; 1: relative; 2: relative to EOF
|
||||
buf = f.read() # read until EOF
|
||||
buf = f.read(n) # read up to n bytes
|
||||
buf = f.readline() # read until end of line ('\n') or EOF
|
||||
list = f.readlines()# list of f.readline() results until EOF
|
||||
f.write(buf) # write at current position
|
||||
f.writelines(list) # for line in list: f.write(line)
|
||||
f.getvalue() # return whole file's contents as a string
|
||||
|
||||
Notes:
|
||||
- Using a real file is often faster (but less convenient).
|
||||
- fileno() is left unimplemented so that code which uses it triggers
|
||||
an exception early.
|
||||
- Seeking far beyond EOF and then writing will insert real null
|
||||
bytes that occupy space in the buffer.
|
||||
- There's a simple test set (see end of this file).
|
||||
"""
|
||||
|
||||
import string
|
||||
|
||||
|
|
|
@ -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:
|
||||
def __init__(self, dict=None):
|
||||
|
|
|
@ -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:
|
||||
def __init__(self, list=None):
|
||||
|
|
1715
Lib/aifc.py
1715
Lib/aifc.py
File diff suppressed because it is too large
Load Diff
|
@ -1,3 +1,5 @@
|
|||
"""Classes for manipulating audio devices (currently only for Sun and SGI)"""
|
||||
|
||||
error = 'audiodev.error'
|
||||
|
||||
class Play_Audio_sgi:
|
||||
|
|
112
Lib/base64.py
112
Lib/base64.py
|
@ -1,7 +1,7 @@
|
|||
#! /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
|
||||
|
||||
import binascii
|
||||
|
@ -9,69 +9,71 @@ import binascii
|
|||
MAXLINESIZE = 76 # Excluding the CRLF
|
||||
MAXBINSIZE = (MAXLINESIZE/4)*3
|
||||
|
||||
# Encode a file.
|
||||
def encode(input, output):
|
||||
while 1:
|
||||
s = input.read(MAXBINSIZE)
|
||||
if not s: break
|
||||
while len(s) < MAXBINSIZE:
|
||||
ns = input.read(MAXBINSIZE-len(s))
|
||||
if not ns: break
|
||||
s = s + ns
|
||||
line = binascii.b2a_base64(s)
|
||||
output.write(line)
|
||||
"""Encode a file."""
|
||||
while 1:
|
||||
s = input.read(MAXBINSIZE)
|
||||
if not s: break
|
||||
while len(s) < MAXBINSIZE:
|
||||
ns = input.read(MAXBINSIZE-len(s))
|
||||
if not ns: break
|
||||
s = s + ns
|
||||
line = binascii.b2a_base64(s)
|
||||
output.write(line)
|
||||
|
||||
# Decode a file.
|
||||
def decode(input, output):
|
||||
while 1:
|
||||
line = input.readline()
|
||||
if not line: break
|
||||
s = binascii.a2b_base64(line)
|
||||
output.write(s)
|
||||
"""Decode a file."""
|
||||
while 1:
|
||||
line = input.readline()
|
||||
if not line: break
|
||||
s = binascii.a2b_base64(line)
|
||||
output.write(s)
|
||||
|
||||
def encodestring(s):
|
||||
import StringIO
|
||||
f = StringIO.StringIO(s)
|
||||
g = StringIO.StringIO()
|
||||
encode(f, g)
|
||||
return g.getvalue()
|
||||
"""Encode a string."""
|
||||
import StringIO
|
||||
f = StringIO.StringIO(s)
|
||||
g = StringIO.StringIO()
|
||||
encode(f, g)
|
||||
return g.getvalue()
|
||||
|
||||
def decodestring(s):
|
||||
import StringIO
|
||||
f = StringIO.StringIO(s)
|
||||
g = StringIO.StringIO()
|
||||
decode(f, g)
|
||||
return g.getvalue()
|
||||
"""Decode a string."""
|
||||
import StringIO
|
||||
f = StringIO.StringIO(s)
|
||||
g = StringIO.StringIO()
|
||||
decode(f, g)
|
||||
return g.getvalue()
|
||||
|
||||
# Small test program
|
||||
def test():
|
||||
import sys, getopt
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], 'deut')
|
||||
except getopt.error, msg:
|
||||
sys.stdout = sys.stderr
|
||||
print msg
|
||||
print """usage: basd64 [-d] [-e] [-u] [-t] [file|-]
|
||||
-d, -u: decode
|
||||
-e: encode (default)
|
||||
-t: decode string 'Aladdin:open sesame'"""
|
||||
sys.exit(2)
|
||||
func = encode
|
||||
for o, a in opts:
|
||||
if o == '-e': func = encode
|
||||
if o == '-d': func = decode
|
||||
if o == '-u': func = decode
|
||||
if o == '-t': test1(); return
|
||||
if args and args[0] != '-':
|
||||
func(open(args[0], 'rb'), sys.stdout)
|
||||
else:
|
||||
func(sys.stdin, sys.stdout)
|
||||
"""Small test program"""
|
||||
import sys, getopt
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], 'deut')
|
||||
except getopt.error, msg:
|
||||
sys.stdout = sys.stderr
|
||||
print msg
|
||||
print """usage: basd64 [-d] [-e] [-u] [-t] [file|-]
|
||||
-d, -u: decode
|
||||
-e: encode (default)
|
||||
-t: decode string 'Aladdin:open sesame'"""
|
||||
sys.exit(2)
|
||||
func = encode
|
||||
for o, a in opts:
|
||||
if o == '-e': func = encode
|
||||
if o == '-d': func = decode
|
||||
if o == '-u': func = decode
|
||||
if o == '-t': test1(); return
|
||||
if args and args[0] != '-':
|
||||
func(open(args[0], 'rb'), sys.stdout)
|
||||
else:
|
||||
func(sys.stdin, sys.stdout)
|
||||
|
||||
def test1():
|
||||
s0 = "Aladdin:open sesame"
|
||||
s1 = encodestring(s0)
|
||||
s2 = decodestring(s1)
|
||||
print s0, `s1`, s2
|
||||
s0 = "Aladdin:open sesame"
|
||||
s1 = encodestring(s0)
|
||||
s2 = decodestring(s1)
|
||||
print s0, `s1`, s2
|
||||
|
||||
if __name__ == '__main__':
|
||||
test()
|
||||
test()
|
||||
|
|
934
Lib/bdb.py
934
Lib/bdb.py
File diff suppressed because it is too large
Load Diff
831
Lib/binhex.py
831
Lib/binhex.py
|
@ -1,4 +1,5 @@
|
|||
"""binhex - Macintosh binhex compression/decompression
|
||||
|
||||
easy interface:
|
||||
binhex(inputfilename, outputfilename)
|
||||
hexbin(inputfilename, outputfilename)
|
||||
|
@ -32,9 +33,9 @@ Error = 'binhex.Error'
|
|||
[_DID_HEADER, _DID_DATA, _DID_RSRC] = range(3)
|
||||
|
||||
# Various constants
|
||||
REASONABLY_LARGE=32768 # Minimal amount we pass the rle-coder
|
||||
REASONABLY_LARGE=32768 # Minimal amount we pass the rle-coder
|
||||
LINELEN=64
|
||||
RUNCHAR=chr(0x90) # run-length introducer
|
||||
RUNCHAR=chr(0x90) # run-length introducer
|
||||
|
||||
#
|
||||
# This code is no longer byte-order dependent
|
||||
|
@ -42,488 +43,488 @@ RUNCHAR=chr(0x90) # run-length introducer
|
|||
#
|
||||
# Workarounds for non-mac machines.
|
||||
if os.name == 'mac':
|
||||
import macfs
|
||||
import MacOS
|
||||
try:
|
||||
openrf = MacOS.openrf
|
||||
except AttributeError:
|
||||
# Backward compatability
|
||||
openrf = open
|
||||
import macfs
|
||||
import MacOS
|
||||
try:
|
||||
openrf = MacOS.openrf
|
||||
except AttributeError:
|
||||
# Backward compatability
|
||||
openrf = open
|
||||
|
||||
def FInfo():
|
||||
return macfs.FInfo()
|
||||
def FInfo():
|
||||
return macfs.FInfo()
|
||||
|
||||
def getfileinfo(name):
|
||||
finfo = macfs.FSSpec(name).GetFInfo()
|
||||
dir, file = os.path.split(name)
|
||||
# XXXX Get resource/data sizes
|
||||
fp = open(name, 'rb')
|
||||
fp.seek(0, 2)
|
||||
dlen = fp.tell()
|
||||
fp = openrf(name, '*rb')
|
||||
fp.seek(0, 2)
|
||||
rlen = fp.tell()
|
||||
return file, finfo, dlen, rlen
|
||||
def getfileinfo(name):
|
||||
finfo = macfs.FSSpec(name).GetFInfo()
|
||||
dir, file = os.path.split(name)
|
||||
# XXXX Get resource/data sizes
|
||||
fp = open(name, 'rb')
|
||||
fp.seek(0, 2)
|
||||
dlen = fp.tell()
|
||||
fp = openrf(name, '*rb')
|
||||
fp.seek(0, 2)
|
||||
rlen = fp.tell()
|
||||
return file, finfo, dlen, rlen
|
||||
|
||||
def openrsrc(name, *mode):
|
||||
if not mode:
|
||||
mode = '*rb'
|
||||
else:
|
||||
mode = '*' + mode[0]
|
||||
return openrf(name, mode)
|
||||
def openrsrc(name, *mode):
|
||||
if not mode:
|
||||
mode = '*rb'
|
||||
else:
|
||||
mode = '*' + mode[0]
|
||||
return openrf(name, mode)
|
||||
|
||||
else:
|
||||
#
|
||||
# Glue code for non-macintosh useage
|
||||
#
|
||||
#
|
||||
# Glue code for non-macintosh useage
|
||||
#
|
||||
|
||||
class FInfo:
|
||||
def __init__(self):
|
||||
self.Type = '????'
|
||||
self.Creator = '????'
|
||||
self.Flags = 0
|
||||
class FInfo:
|
||||
def __init__(self):
|
||||
self.Type = '????'
|
||||
self.Creator = '????'
|
||||
self.Flags = 0
|
||||
|
||||
def getfileinfo(name):
|
||||
finfo = FInfo()
|
||||
# Quick check for textfile
|
||||
fp = open(name)
|
||||
data = open(name).read(256)
|
||||
for c in data:
|
||||
if not c in string.whitespace \
|
||||
and (c<' ' or ord(c) > 0177):
|
||||
break
|
||||
else:
|
||||
finfo.Type = 'TEXT'
|
||||
fp.seek(0, 2)
|
||||
dsize = fp.tell()
|
||||
fp.close()
|
||||
dir, file = os.path.split(name)
|
||||
file = string.replace(file, ':', '-', 1)
|
||||
return file, finfo, dsize, 0
|
||||
def getfileinfo(name):
|
||||
finfo = FInfo()
|
||||
# Quick check for textfile
|
||||
fp = open(name)
|
||||
data = open(name).read(256)
|
||||
for c in data:
|
||||
if not c in string.whitespace \
|
||||
and (c<' ' or ord(c) > 0177):
|
||||
break
|
||||
else:
|
||||
finfo.Type = 'TEXT'
|
||||
fp.seek(0, 2)
|
||||
dsize = fp.tell()
|
||||
fp.close()
|
||||
dir, file = os.path.split(name)
|
||||
file = string.replace(file, ':', '-', 1)
|
||||
return file, finfo, dsize, 0
|
||||
|
||||
class openrsrc:
|
||||
def __init__(self, *args):
|
||||
pass
|
||||
class openrsrc:
|
||||
def __init__(self, *args):
|
||||
pass
|
||||
|
||||
def read(self, *args):
|
||||
return ''
|
||||
def read(self, *args):
|
||||
return ''
|
||||
|
||||
def write(self, *args):
|
||||
pass
|
||||
def write(self, *args):
|
||||
pass
|
||||
|
||||
def close(self):
|
||||
pass
|
||||
def close(self):
|
||||
pass
|
||||
|
||||
class _Hqxcoderengine:
|
||||
"""Write data to the coder in 3-byte chunks"""
|
||||
"""Write data to the coder in 3-byte chunks"""
|
||||
|
||||
def __init__(self, ofp):
|
||||
self.ofp = ofp
|
||||
self.data = ''
|
||||
self.hqxdata = ''
|
||||
self.linelen = LINELEN-1
|
||||
def __init__(self, ofp):
|
||||
self.ofp = ofp
|
||||
self.data = ''
|
||||
self.hqxdata = ''
|
||||
self.linelen = LINELEN-1
|
||||
|
||||
def write(self, data):
|
||||
self.data = self.data + data
|
||||
datalen = len(self.data)
|
||||
todo = (datalen/3)*3
|
||||
data = self.data[:todo]
|
||||
self.data = self.data[todo:]
|
||||
if not data:
|
||||
return
|
||||
self.hqxdata = self.hqxdata + binascii.b2a_hqx(data)
|
||||
self._flush(0)
|
||||
def write(self, data):
|
||||
self.data = self.data + data
|
||||
datalen = len(self.data)
|
||||
todo = (datalen/3)*3
|
||||
data = self.data[:todo]
|
||||
self.data = self.data[todo:]
|
||||
if not data:
|
||||
return
|
||||
self.hqxdata = self.hqxdata + binascii.b2a_hqx(data)
|
||||
self._flush(0)
|
||||
|
||||
def _flush(self, force):
|
||||
first = 0
|
||||
while first <= len(self.hqxdata)-self.linelen:
|
||||
last = first + self.linelen
|
||||
self.ofp.write(self.hqxdata[first:last]+'\n')
|
||||
self.linelen = LINELEN
|
||||
first = last
|
||||
self.hqxdata = self.hqxdata[first:]
|
||||
if force:
|
||||
self.ofp.write(self.hqxdata + ':\n')
|
||||
def _flush(self, force):
|
||||
first = 0
|
||||
while first <= len(self.hqxdata)-self.linelen:
|
||||
last = first + self.linelen
|
||||
self.ofp.write(self.hqxdata[first:last]+'\n')
|
||||
self.linelen = LINELEN
|
||||
first = last
|
||||
self.hqxdata = self.hqxdata[first:]
|
||||
if force:
|
||||
self.ofp.write(self.hqxdata + ':\n')
|
||||
|
||||
def close(self):
|
||||
if self.data:
|
||||
self.hqxdata = \
|
||||
self.hqxdata + binascii.b2a_hqx(self.data)
|
||||
self._flush(1)
|
||||
self.ofp.close()
|
||||
del self.ofp
|
||||
def close(self):
|
||||
if self.data:
|
||||
self.hqxdata = \
|
||||
self.hqxdata + binascii.b2a_hqx(self.data)
|
||||
self._flush(1)
|
||||
self.ofp.close()
|
||||
del self.ofp
|
||||
|
||||
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):
|
||||
self.ofp = ofp
|
||||
self.data = ''
|
||||
def __init__(self, ofp):
|
||||
self.ofp = ofp
|
||||
self.data = ''
|
||||
|
||||
def write(self, data):
|
||||
self.data = self.data + data
|
||||
if len(self.data) < REASONABLY_LARGE:
|
||||
return
|
||||
rledata = binascii.rlecode_hqx(self.data)
|
||||
self.ofp.write(rledata)
|
||||
self.data = ''
|
||||
def write(self, data):
|
||||
self.data = self.data + data
|
||||
if len(self.data) < REASONABLY_LARGE:
|
||||
return
|
||||
rledata = binascii.rlecode_hqx(self.data)
|
||||
self.ofp.write(rledata)
|
||||
self.data = ''
|
||||
|
||||
def close(self):
|
||||
if self.data:
|
||||
rledata = binascii.rlecode_hqx(self.data)
|
||||
self.ofp.write(rledata)
|
||||
self.ofp.close()
|
||||
del self.ofp
|
||||
def close(self):
|
||||
if self.data:
|
||||
rledata = binascii.rlecode_hqx(self.data)
|
||||
self.ofp.write(rledata)
|
||||
self.ofp.close()
|
||||
del self.ofp
|
||||
|
||||
class BinHex:
|
||||
def __init__(self, (name, finfo, dlen, rlen), ofp):
|
||||
if type(ofp) == type(''):
|
||||
ofname = ofp
|
||||
ofp = open(ofname, 'w')
|
||||
if os.name == 'mac':
|
||||
fss = macfs.FSSpec(ofname)
|
||||
fss.SetCreatorType('BnHq', 'TEXT')
|
||||
ofp.write('(This file must be converted with BinHex 4.0)\n\n:')
|
||||
hqxer = _Hqxcoderengine(ofp)
|
||||
self.ofp = _Rlecoderengine(hqxer)
|
||||
self.crc = 0
|
||||
if finfo == None:
|
||||
finfo = FInfo()
|
||||
self.dlen = dlen
|
||||
self.rlen = rlen
|
||||
self._writeinfo(name, finfo)
|
||||
self.state = _DID_HEADER
|
||||
def __init__(self, (name, finfo, dlen, rlen), ofp):
|
||||
if type(ofp) == type(''):
|
||||
ofname = ofp
|
||||
ofp = open(ofname, 'w')
|
||||
if os.name == 'mac':
|
||||
fss = macfs.FSSpec(ofname)
|
||||
fss.SetCreatorType('BnHq', 'TEXT')
|
||||
ofp.write('(This file must be converted with BinHex 4.0)\n\n:')
|
||||
hqxer = _Hqxcoderengine(ofp)
|
||||
self.ofp = _Rlecoderengine(hqxer)
|
||||
self.crc = 0
|
||||
if finfo == None:
|
||||
finfo = FInfo()
|
||||
self.dlen = dlen
|
||||
self.rlen = rlen
|
||||
self._writeinfo(name, finfo)
|
||||
self.state = _DID_HEADER
|
||||
|
||||
def _writeinfo(self, name, finfo):
|
||||
name = name
|
||||
nl = len(name)
|
||||
if nl > 63:
|
||||
raise Error, 'Filename too long'
|
||||
d = chr(nl) + name + '\0'
|
||||
d2 = finfo.Type + finfo.Creator
|
||||
def _writeinfo(self, name, finfo):
|
||||
name = name
|
||||
nl = len(name)
|
||||
if nl > 63:
|
||||
raise Error, 'Filename too long'
|
||||
d = chr(nl) + name + '\0'
|
||||
d2 = finfo.Type + finfo.Creator
|
||||
|
||||
# Force all structs to be packed with big-endian
|
||||
d3 = struct.pack('>h', finfo.Flags)
|
||||
d4 = struct.pack('>ii', self.dlen, self.rlen)
|
||||
info = d + d2 + d3 + d4
|
||||
self._write(info)
|
||||
self._writecrc()
|
||||
# Force all structs to be packed with big-endian
|
||||
d3 = struct.pack('>h', finfo.Flags)
|
||||
d4 = struct.pack('>ii', self.dlen, self.rlen)
|
||||
info = d + d2 + d3 + d4
|
||||
self._write(info)
|
||||
self._writecrc()
|
||||
|
||||
def _write(self, data):
|
||||
self.crc = binascii.crc_hqx(data, self.crc)
|
||||
self.ofp.write(data)
|
||||
def _write(self, data):
|
||||
self.crc = binascii.crc_hqx(data, self.crc)
|
||||
self.ofp.write(data)
|
||||
|
||||
def _writecrc(self):
|
||||
# XXXX Should this be here??
|
||||
# self.crc = binascii.crc_hqx('\0\0', self.crc)
|
||||
self.ofp.write(struct.pack('>h', self.crc))
|
||||
self.crc = 0
|
||||
def _writecrc(self):
|
||||
# XXXX Should this be here??
|
||||
# self.crc = binascii.crc_hqx('\0\0', self.crc)
|
||||
self.ofp.write(struct.pack('>h', self.crc))
|
||||
self.crc = 0
|
||||
|
||||
def write(self, data):
|
||||
if self.state != _DID_HEADER:
|
||||
raise Error, 'Writing data at the wrong time'
|
||||
self.dlen = self.dlen - len(data)
|
||||
self._write(data)
|
||||
def write(self, data):
|
||||
if self.state != _DID_HEADER:
|
||||
raise Error, 'Writing data at the wrong time'
|
||||
self.dlen = self.dlen - len(data)
|
||||
self._write(data)
|
||||
|
||||
def close_data(self):
|
||||
if self.dlen <> 0:
|
||||
raise Error, 'Incorrect data size, diff='+`self.rlen`
|
||||
self._writecrc()
|
||||
self.state = _DID_DATA
|
||||
def close_data(self):
|
||||
if self.dlen <> 0:
|
||||
raise Error, 'Incorrect data size, diff='+`self.rlen`
|
||||
self._writecrc()
|
||||
self.state = _DID_DATA
|
||||
|
||||
def write_rsrc(self, data):
|
||||
if self.state < _DID_DATA:
|
||||
self.close_data()
|
||||
if self.state != _DID_DATA:
|
||||
raise Error, 'Writing resource data at the wrong time'
|
||||
self.rlen = self.rlen - len(data)
|
||||
self._write(data)
|
||||
def write_rsrc(self, data):
|
||||
if self.state < _DID_DATA:
|
||||
self.close_data()
|
||||
if self.state != _DID_DATA:
|
||||
raise Error, 'Writing resource data at the wrong time'
|
||||
self.rlen = self.rlen - len(data)
|
||||
self._write(data)
|
||||
|
||||
def close(self):
|
||||
if self.state < _DID_DATA:
|
||||
self.close_data()
|
||||
if self.state != _DID_DATA:
|
||||
raise Error, 'Close at the wrong time'
|
||||
if self.rlen <> 0:
|
||||
raise Error, \
|
||||
"Incorrect resource-datasize, diff="+`self.rlen`
|
||||
self._writecrc()
|
||||
self.ofp.close()
|
||||
self.state = None
|
||||
del self.ofp
|
||||
def close(self):
|
||||
if self.state < _DID_DATA:
|
||||
self.close_data()
|
||||
if self.state != _DID_DATA:
|
||||
raise Error, 'Close at the wrong time'
|
||||
if self.rlen <> 0:
|
||||
raise Error, \
|
||||
"Incorrect resource-datasize, diff="+`self.rlen`
|
||||
self._writecrc()
|
||||
self.ofp.close()
|
||||
self.state = None
|
||||
del self.ofp
|
||||
|
||||
def binhex(inp, out):
|
||||
"""(infilename, outfilename) - Create binhex-encoded copy of a file"""
|
||||
finfo = getfileinfo(inp)
|
||||
ofp = BinHex(finfo, out)
|
||||
"""(infilename, outfilename) - Create binhex-encoded copy of a file"""
|
||||
finfo = getfileinfo(inp)
|
||||
ofp = BinHex(finfo, out)
|
||||
|
||||
ifp = open(inp, 'rb')
|
||||
# XXXX Do textfile translation on non-mac systems
|
||||
while 1:
|
||||
d = ifp.read(128000)
|
||||
if not d: break
|
||||
ofp.write(d)
|
||||
ofp.close_data()
|
||||
ifp.close()
|
||||
ifp = open(inp, 'rb')
|
||||
# XXXX Do textfile translation on non-mac systems
|
||||
while 1:
|
||||
d = ifp.read(128000)
|
||||
if not d: break
|
||||
ofp.write(d)
|
||||
ofp.close_data()
|
||||
ifp.close()
|
||||
|
||||
ifp = openrsrc(inp, 'rb')
|
||||
while 1:
|
||||
d = ifp.read(128000)
|
||||
if not d: break
|
||||
ofp.write_rsrc(d)
|
||||
ofp.close()
|
||||
ifp.close()
|
||||
ifp = openrsrc(inp, 'rb')
|
||||
while 1:
|
||||
d = ifp.read(128000)
|
||||
if not d: break
|
||||
ofp.write_rsrc(d)
|
||||
ofp.close()
|
||||
ifp.close()
|
||||
|
||||
class _Hqxdecoderengine:
|
||||
"""Read data via the decoder in 4-byte chunks"""
|
||||
"""Read data via the decoder in 4-byte chunks"""
|
||||
|
||||
def __init__(self, ifp):
|
||||
self.ifp = ifp
|
||||
self.eof = 0
|
||||
def __init__(self, ifp):
|
||||
self.ifp = ifp
|
||||
self.eof = 0
|
||||
|
||||
def read(self, totalwtd):
|
||||
"""Read at least wtd bytes (or until EOF)"""
|
||||
decdata = ''
|
||||
wtd = totalwtd
|
||||
#
|
||||
# The loop here is convoluted, since we don't really now how
|
||||
# much to decode: there may be newlines in the incoming data.
|
||||
while wtd > 0:
|
||||
if self.eof: return decdata
|
||||
wtd = ((wtd+2)/3)*4
|
||||
data = self.ifp.read(wtd)
|
||||
#
|
||||
# Next problem: there may not be a complete number of
|
||||
# bytes in what we pass to a2b. Solve by yet another
|
||||
# loop.
|
||||
#
|
||||
while 1:
|
||||
try:
|
||||
decdatacur, self.eof = \
|
||||
binascii.a2b_hqx(data)
|
||||
break
|
||||
except binascii.Incomplete:
|
||||
pass
|
||||
newdata = self.ifp.read(1)
|
||||
if not newdata:
|
||||
raise Error, \
|
||||
'Premature EOF on binhex file'
|
||||
data = data + newdata
|
||||
decdata = decdata + decdatacur
|
||||
wtd = totalwtd - len(decdata)
|
||||
if not decdata and not self.eof:
|
||||
raise Error, 'Premature EOF on binhex file'
|
||||
return decdata
|
||||
def read(self, totalwtd):
|
||||
"""Read at least wtd bytes (or until EOF)"""
|
||||
decdata = ''
|
||||
wtd = totalwtd
|
||||
#
|
||||
# The loop here is convoluted, since we don't really now how
|
||||
# much to decode: there may be newlines in the incoming data.
|
||||
while wtd > 0:
|
||||
if self.eof: return decdata
|
||||
wtd = ((wtd+2)/3)*4
|
||||
data = self.ifp.read(wtd)
|
||||
#
|
||||
# Next problem: there may not be a complete number of
|
||||
# bytes in what we pass to a2b. Solve by yet another
|
||||
# loop.
|
||||
#
|
||||
while 1:
|
||||
try:
|
||||
decdatacur, self.eof = \
|
||||
binascii.a2b_hqx(data)
|
||||
break
|
||||
except binascii.Incomplete:
|
||||
pass
|
||||
newdata = self.ifp.read(1)
|
||||
if not newdata:
|
||||
raise Error, \
|
||||
'Premature EOF on binhex file'
|
||||
data = data + newdata
|
||||
decdata = decdata + decdatacur
|
||||
wtd = totalwtd - len(decdata)
|
||||
if not decdata and not self.eof:
|
||||
raise Error, 'Premature EOF on binhex file'
|
||||
return decdata
|
||||
|
||||
def close(self):
|
||||
self.ifp.close()
|
||||
def close(self):
|
||||
self.ifp.close()
|
||||
|
||||
class _Rledecoderengine:
|
||||
"""Read data via the RLE-coder"""
|
||||
"""Read data via the RLE-coder"""
|
||||
|
||||
def __init__(self, ifp):
|
||||
self.ifp = ifp
|
||||
self.pre_buffer = ''
|
||||
self.post_buffer = ''
|
||||
self.eof = 0
|
||||
def __init__(self, ifp):
|
||||
self.ifp = ifp
|
||||
self.pre_buffer = ''
|
||||
self.post_buffer = ''
|
||||
self.eof = 0
|
||||
|
||||
def read(self, wtd):
|
||||
if wtd > len(self.post_buffer):
|
||||
self._fill(wtd-len(self.post_buffer))
|
||||
rv = self.post_buffer[:wtd]
|
||||
self.post_buffer = self.post_buffer[wtd:]
|
||||
return rv
|
||||
def read(self, wtd):
|
||||
if wtd > len(self.post_buffer):
|
||||
self._fill(wtd-len(self.post_buffer))
|
||||
rv = self.post_buffer[:wtd]
|
||||
self.post_buffer = self.post_buffer[wtd:]
|
||||
return rv
|
||||
|
||||
def _fill(self, wtd):
|
||||
self.pre_buffer = self.pre_buffer + self.ifp.read(wtd+4)
|
||||
if self.ifp.eof:
|
||||
self.post_buffer = self.post_buffer + \
|
||||
binascii.rledecode_hqx(self.pre_buffer)
|
||||
self.pre_buffer = ''
|
||||
return
|
||||
def _fill(self, wtd):
|
||||
self.pre_buffer = self.pre_buffer + self.ifp.read(wtd+4)
|
||||
if self.ifp.eof:
|
||||
self.post_buffer = self.post_buffer + \
|
||||
binascii.rledecode_hqx(self.pre_buffer)
|
||||
self.pre_buffer = ''
|
||||
return
|
||||
|
||||
#
|
||||
# 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
|
||||
# of bytes in the buffer, depending on what the end of
|
||||
# the buffer looks like:
|
||||
# '\220\0\220' - Keep 3 bytes: repeated \220 (escaped as \220\0)
|
||||
# '?\220' - Keep 2 bytes: repeated something-else
|
||||
# '\220\0' - Escaped \220: Keep 2 bytes.
|
||||
# '?\220?' - Complete repeat sequence: decode all
|
||||
# otherwise: keep 1 byte.
|
||||
#
|
||||
mark = len(self.pre_buffer)
|
||||
if self.pre_buffer[-3:] == RUNCHAR + '\0' + RUNCHAR:
|
||||
mark = mark - 3
|
||||
elif self.pre_buffer[-1] == RUNCHAR:
|
||||
mark = mark - 2
|
||||
elif self.pre_buffer[-2:] == RUNCHAR + '\0':
|
||||
mark = mark - 2
|
||||
elif self.pre_buffer[-2] == RUNCHAR:
|
||||
pass # Decode all
|
||||
else:
|
||||
mark = mark - 1
|
||||
#
|
||||
# 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
|
||||
# of bytes in the buffer, depending on what the end of
|
||||
# the buffer looks like:
|
||||
# '\220\0\220' - Keep 3 bytes: repeated \220 (escaped as \220\0)
|
||||
# '?\220' - Keep 2 bytes: repeated something-else
|
||||
# '\220\0' - Escaped \220: Keep 2 bytes.
|
||||
# '?\220?' - Complete repeat sequence: decode all
|
||||
# otherwise: keep 1 byte.
|
||||
#
|
||||
mark = len(self.pre_buffer)
|
||||
if self.pre_buffer[-3:] == RUNCHAR + '\0' + RUNCHAR:
|
||||
mark = mark - 3
|
||||
elif self.pre_buffer[-1] == RUNCHAR:
|
||||
mark = mark - 2
|
||||
elif self.pre_buffer[-2:] == RUNCHAR + '\0':
|
||||
mark = mark - 2
|
||||
elif self.pre_buffer[-2] == RUNCHAR:
|
||||
pass # Decode all
|
||||
else:
|
||||
mark = mark - 1
|
||||
|
||||
self.post_buffer = self.post_buffer + \
|
||||
binascii.rledecode_hqx(self.pre_buffer[:mark])
|
||||
self.pre_buffer = self.pre_buffer[mark:]
|
||||
self.post_buffer = self.post_buffer + \
|
||||
binascii.rledecode_hqx(self.pre_buffer[:mark])
|
||||
self.pre_buffer = self.pre_buffer[mark:]
|
||||
|
||||
def close(self):
|
||||
self.ifp.close()
|
||||
def close(self):
|
||||
self.ifp.close()
|
||||
|
||||
class HexBin:
|
||||
def __init__(self, ifp):
|
||||
if type(ifp) == type(''):
|
||||
ifp = open(ifp)
|
||||
#
|
||||
# Find initial colon.
|
||||
#
|
||||
while 1:
|
||||
ch = ifp.read(1)
|
||||
if not ch:
|
||||
raise Error, "No binhex data found"
|
||||
# Cater for \r\n terminated lines (which show up as \n\r, hence
|
||||
# all lines start with \r)
|
||||
if ch == '\r':
|
||||
continue
|
||||
if ch == ':':
|
||||
break
|
||||
if ch != '\n':
|
||||
dummy = ifp.readline()
|
||||
def __init__(self, ifp):
|
||||
if type(ifp) == type(''):
|
||||
ifp = open(ifp)
|
||||
#
|
||||
# Find initial colon.
|
||||
#
|
||||
while 1:
|
||||
ch = ifp.read(1)
|
||||
if not ch:
|
||||
raise Error, "No binhex data found"
|
||||
# Cater for \r\n terminated lines (which show up as \n\r, hence
|
||||
# all lines start with \r)
|
||||
if ch == '\r':
|
||||
continue
|
||||
if ch == ':':
|
||||
break
|
||||
if ch != '\n':
|
||||
dummy = ifp.readline()
|
||||
|
||||
hqxifp = _Hqxdecoderengine(ifp)
|
||||
self.ifp = _Rledecoderengine(hqxifp)
|
||||
self.crc = 0
|
||||
self._readheader()
|
||||
hqxifp = _Hqxdecoderengine(ifp)
|
||||
self.ifp = _Rledecoderengine(hqxifp)
|
||||
self.crc = 0
|
||||
self._readheader()
|
||||
|
||||
def _read(self, len):
|
||||
data = self.ifp.read(len)
|
||||
self.crc = binascii.crc_hqx(data, self.crc)
|
||||
return data
|
||||
def _read(self, len):
|
||||
data = self.ifp.read(len)
|
||||
self.crc = binascii.crc_hqx(data, self.crc)
|
||||
return data
|
||||
|
||||
def _checkcrc(self):
|
||||
filecrc = struct.unpack('>h', self.ifp.read(2))[0] & 0xffff
|
||||
#self.crc = binascii.crc_hqx('\0\0', self.crc)
|
||||
# XXXX Is this needed??
|
||||
self.crc = self.crc & 0xffff
|
||||
if filecrc != self.crc:
|
||||
raise Error, 'CRC error, computed %x, read %x' \
|
||||
%(self.crc, filecrc)
|
||||
self.crc = 0
|
||||
def _checkcrc(self):
|
||||
filecrc = struct.unpack('>h', self.ifp.read(2))[0] & 0xffff
|
||||
#self.crc = binascii.crc_hqx('\0\0', self.crc)
|
||||
# XXXX Is this needed??
|
||||
self.crc = self.crc & 0xffff
|
||||
if filecrc != self.crc:
|
||||
raise Error, 'CRC error, computed %x, read %x' \
|
||||
%(self.crc, filecrc)
|
||||
self.crc = 0
|
||||
|
||||
def _readheader(self):
|
||||
len = self._read(1)
|
||||
fname = self._read(ord(len))
|
||||
rest = self._read(1+4+4+2+4+4)
|
||||
self._checkcrc()
|
||||
def _readheader(self):
|
||||
len = self._read(1)
|
||||
fname = self._read(ord(len))
|
||||
rest = self._read(1+4+4+2+4+4)
|
||||
self._checkcrc()
|
||||
|
||||
type = rest[1:5]
|
||||
creator = rest[5:9]
|
||||
flags = struct.unpack('>h', rest[9:11])[0]
|
||||
self.dlen = struct.unpack('>l', rest[11:15])[0]
|
||||
self.rlen = struct.unpack('>l', rest[15:19])[0]
|
||||
type = rest[1:5]
|
||||
creator = rest[5:9]
|
||||
flags = struct.unpack('>h', rest[9:11])[0]
|
||||
self.dlen = struct.unpack('>l', rest[11:15])[0]
|
||||
self.rlen = struct.unpack('>l', rest[15:19])[0]
|
||||
|
||||
self.FName = fname
|
||||
self.FInfo = FInfo()
|
||||
self.FInfo.Creator = creator
|
||||
self.FInfo.Type = type
|
||||
self.FInfo.Flags = flags
|
||||
self.FName = fname
|
||||
self.FInfo = FInfo()
|
||||
self.FInfo.Creator = creator
|
||||
self.FInfo.Type = type
|
||||
self.FInfo.Flags = flags
|
||||
|
||||
self.state = _DID_HEADER
|
||||
self.state = _DID_HEADER
|
||||
|
||||
def read(self, *n):
|
||||
if self.state != _DID_HEADER:
|
||||
raise Error, 'Read data at wrong time'
|
||||
if n:
|
||||
n = n[0]
|
||||
n = min(n, self.dlen)
|
||||
else:
|
||||
n = self.dlen
|
||||
rv = ''
|
||||
while len(rv) < n:
|
||||
rv = rv + self._read(n-len(rv))
|
||||
self.dlen = self.dlen - n
|
||||
return rv
|
||||
def read(self, *n):
|
||||
if self.state != _DID_HEADER:
|
||||
raise Error, 'Read data at wrong time'
|
||||
if n:
|
||||
n = n[0]
|
||||
n = min(n, self.dlen)
|
||||
else:
|
||||
n = self.dlen
|
||||
rv = ''
|
||||
while len(rv) < n:
|
||||
rv = rv + self._read(n-len(rv))
|
||||
self.dlen = self.dlen - n
|
||||
return rv
|
||||
|
||||
def close_data(self):
|
||||
if self.state != _DID_HEADER:
|
||||
raise Error, 'close_data at wrong time'
|
||||
if self.dlen:
|
||||
dummy = self._read(self.dlen)
|
||||
self._checkcrc()
|
||||
self.state = _DID_DATA
|
||||
def close_data(self):
|
||||
if self.state != _DID_HEADER:
|
||||
raise Error, 'close_data at wrong time'
|
||||
if self.dlen:
|
||||
dummy = self._read(self.dlen)
|
||||
self._checkcrc()
|
||||
self.state = _DID_DATA
|
||||
|
||||
def read_rsrc(self, *n):
|
||||
if self.state == _DID_HEADER:
|
||||
self.close_data()
|
||||
if self.state != _DID_DATA:
|
||||
raise Error, 'Read resource data at wrong time'
|
||||
if n:
|
||||
n = n[0]
|
||||
n = min(n, self.rlen)
|
||||
else:
|
||||
n = self.rlen
|
||||
self.rlen = self.rlen - n
|
||||
return self._read(n)
|
||||
def read_rsrc(self, *n):
|
||||
if self.state == _DID_HEADER:
|
||||
self.close_data()
|
||||
if self.state != _DID_DATA:
|
||||
raise Error, 'Read resource data at wrong time'
|
||||
if n:
|
||||
n = n[0]
|
||||
n = min(n, self.rlen)
|
||||
else:
|
||||
n = self.rlen
|
||||
self.rlen = self.rlen - n
|
||||
return self._read(n)
|
||||
|
||||
def close(self):
|
||||
if self.rlen:
|
||||
dummy = self.read_rsrc(self.rlen)
|
||||
self._checkcrc()
|
||||
self.state = _DID_RSRC
|
||||
self.ifp.close()
|
||||
def close(self):
|
||||
if self.rlen:
|
||||
dummy = self.read_rsrc(self.rlen)
|
||||
self._checkcrc()
|
||||
self.state = _DID_RSRC
|
||||
self.ifp.close()
|
||||
|
||||
def hexbin(inp, out):
|
||||
"""(infilename, outfilename) - Decode binhexed file"""
|
||||
ifp = HexBin(inp)
|
||||
finfo = ifp.FInfo
|
||||
if not out:
|
||||
out = ifp.FName
|
||||
if os.name == 'mac':
|
||||
ofss = macfs.FSSpec(out)
|
||||
out = ofss.as_pathname()
|
||||
"""(infilename, outfilename) - Decode binhexed file"""
|
||||
ifp = HexBin(inp)
|
||||
finfo = ifp.FInfo
|
||||
if not out:
|
||||
out = ifp.FName
|
||||
if os.name == 'mac':
|
||||
ofss = macfs.FSSpec(out)
|
||||
out = ofss.as_pathname()
|
||||
|
||||
ofp = open(out, 'wb')
|
||||
# XXXX Do translation on non-mac systems
|
||||
while 1:
|
||||
d = ifp.read(128000)
|
||||
if not d: break
|
||||
ofp.write(d)
|
||||
ofp.close()
|
||||
ifp.close_data()
|
||||
ofp = open(out, 'wb')
|
||||
# XXXX Do translation on non-mac systems
|
||||
while 1:
|
||||
d = ifp.read(128000)
|
||||
if not d: break
|
||||
ofp.write(d)
|
||||
ofp.close()
|
||||
ifp.close_data()
|
||||
|
||||
d = ifp.read_rsrc(128000)
|
||||
if d:
|
||||
ofp = openrsrc(out, 'wb')
|
||||
ofp.write(d)
|
||||
while 1:
|
||||
d = ifp.read_rsrc(128000)
|
||||
if not d: break
|
||||
ofp.write(d)
|
||||
ofp.close()
|
||||
d = ifp.read_rsrc(128000)
|
||||
if d:
|
||||
ofp = openrsrc(out, 'wb')
|
||||
ofp.write(d)
|
||||
while 1:
|
||||
d = ifp.read_rsrc(128000)
|
||||
if not d: break
|
||||
ofp.write(d)
|
||||
ofp.close()
|
||||
|
||||
if os.name == 'mac':
|
||||
nfinfo = ofss.GetFInfo()
|
||||
nfinfo.Creator = finfo.Creator
|
||||
nfinfo.Type = finfo.Type
|
||||
nfinfo.Flags = finfo.Flags
|
||||
ofss.SetFInfo(nfinfo)
|
||||
if os.name == 'mac':
|
||||
nfinfo = ofss.GetFInfo()
|
||||
nfinfo.Creator = finfo.Creator
|
||||
nfinfo.Type = finfo.Type
|
||||
nfinfo.Flags = finfo.Flags
|
||||
ofss.SetFInfo(nfinfo)
|
||||
|
||||
ifp.close()
|
||||
ifp.close()
|
||||
|
||||
def _test():
|
||||
if os.name == 'mac':
|
||||
fss, ok = macfs.PromptGetFile('File to convert:')
|
||||
if not ok:
|
||||
sys.exit(0)
|
||||
fname = fss.as_pathname()
|
||||
else:
|
||||
fname = sys.argv[1]
|
||||
binhex(fname, fname+'.hqx')
|
||||
hexbin(fname+'.hqx', fname+'.viahqx')
|
||||
#hexbin(fname, fname+'.unpacked')
|
||||
sys.exit(1)
|
||||
if os.name == 'mac':
|
||||
fss, ok = macfs.PromptGetFile('File to convert:')
|
||||
if not ok:
|
||||
sys.exit(0)
|
||||
fname = fss.as_pathname()
|
||||
else:
|
||||
fname = sys.argv[1]
|
||||
binhex(fname, fname+'.hqx')
|
||||
hexbin(fname+'.hqx', fname+'.viahqx')
|
||||
#hexbin(fname, fname+'.unpacked')
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
_test()
|
||||
_test()
|
||||
|
|
|
@ -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):
|
||||
if hi is None:
|
||||
hi = len(a)
|
||||
while lo < hi:
|
||||
mid = (lo+hi)/2
|
||||
if x < a[mid]: hi = mid
|
||||
else: lo = mid+1
|
||||
a.insert(lo, x)
|
||||
"""Insert item x in list a, and keep it sorted assuming a is sorted."""
|
||||
if hi is None:
|
||||
hi = len(a)
|
||||
while lo < hi:
|
||||
mid = (lo+hi)/2
|
||||
if x < a[mid]: hi = mid
|
||||
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):
|
||||
if hi is None:
|
||||
hi = len(a)
|
||||
while lo < hi:
|
||||
mid = (lo+hi)/2
|
||||
if x < a[mid]: hi = mid
|
||||
else: lo = mid+1
|
||||
return lo
|
||||
"""Find the index where to insert item x in list a, assuming a is sorted."""
|
||||
if hi is None:
|
||||
hi = len(a)
|
||||
while lo < hi:
|
||||
mid = (lo+hi)/2
|
||||
if x < a[mid]: hi = mid
|
||||
else: lo = mid+1
|
||||
return lo
|
||||
|
|
226
Lib/calendar.py
226
Lib/calendar.py
|
@ -1,6 +1,4 @@
|
|||
###############################
|
||||
# Calendar printing functions #
|
||||
###############################
|
||||
"""Calendar printing functions"""
|
||||
|
||||
# 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]
|
||||
|
||||
# Full and abbreviated names of weekdays
|
||||
day_name = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', \
|
||||
'Friday', 'Saturday', 'Sunday']
|
||||
day_name = ['Monday', 'Tuesday', 'Wednesday', 'Thursday',
|
||||
'Friday', 'Saturday', 'Sunday']
|
||||
day_abbr = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
|
||||
|
||||
# Full and abbreviated names of months (1-based arrays!!!)
|
||||
month_name = ['', 'January', 'February', 'March', 'April', \
|
||||
'May', 'June', 'July', 'August', \
|
||||
'September', 'October', 'November', 'December']
|
||||
month_abbr = [' ', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', \
|
||||
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
|
||||
month_name = ['', 'January', 'February', 'March', 'April',
|
||||
'May', 'June', 'July', 'August',
|
||||
'September', 'October', 'November', 'December']
|
||||
month_abbr = [' ', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
|
||||
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
|
||||
|
||||
# Return 1 for leap years, 0 for non-leap years
|
||||
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):
|
||||
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):
|
||||
secs = mktime((year, month, day, 0, 0, 0, 0, 0, 0))
|
||||
tuple = localtime(secs)
|
||||
return tuple[6]
|
||||
"""Return weekday (0-6 ~ Mon-Sun) for year (1970-...), month (1-12), day (1-31)."""
|
||||
secs = mktime((year, month, day, 0, 0, 0, 0, 0, 0))
|
||||
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):
|
||||
if not 1 <= month <= 12: raise ValueError, 'bad month number'
|
||||
day1 = weekday(year, month, 1)
|
||||
ndays = mdays[month] + (month == February and isleap(year))
|
||||
return day1, ndays
|
||||
"""Return weekday (0-6 ~ Mon-Sun) and number of days (28-31) for year, month."""
|
||||
if not 1 <= month <= 12: raise ValueError, 'bad month number'
|
||||
day1 = weekday(year, month, 1)
|
||||
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):
|
||||
day1, ndays = monthrange(year, month)
|
||||
rows = []
|
||||
r7 = range(7)
|
||||
day = 1 - day1
|
||||
while day <= ndays:
|
||||
row = [0, 0, 0, 0, 0, 0, 0]
|
||||
for i in r7:
|
||||
if 1 <= day <= ndays: row[i] = day
|
||||
day = day + 1
|
||||
rows.append(row)
|
||||
return rows
|
||||
"""Return a matrix representing a month's calendar.
|
||||
Each row represents a week; days outside this month are zero."""
|
||||
day1, ndays = monthrange(year, month)
|
||||
rows = []
|
||||
r7 = range(7)
|
||||
day = 1 - day1
|
||||
while day <= ndays:
|
||||
row = [0, 0, 0, 0, 0, 0, 0]
|
||||
for i in r7:
|
||||
if 1 <= day <= ndays: row[i] = day
|
||||
day = day + 1
|
||||
rows.append(row)
|
||||
return rows
|
||||
|
||||
# Caching interface to _monthcalendar
|
||||
_mc_cache = {}
|
||||
def monthcalendar(year, month):
|
||||
key = (year, month)
|
||||
if _mc_cache.has_key(key):
|
||||
return _mc_cache[key]
|
||||
else:
|
||||
_mc_cache[key] = ret = _monthcalendar(year, month)
|
||||
return ret
|
||||
"""Caching interface to _monthcalendar."""
|
||||
key = (year, month)
|
||||
if _mc_cache.has_key(key):
|
||||
return _mc_cache[key]
|
||||
else:
|
||||
_mc_cache[key] = ret = _monthcalendar(year, month)
|
||||
return ret
|
||||
|
||||
# Center a string in a field
|
||||
def _center(str, width):
|
||||
n = width - len(str)
|
||||
if n <= 0: return str
|
||||
return ' '*((n+1)/2) + str + ' '*((n)/2)
|
||||
"""Center a string in a field."""
|
||||
n = width - len(str)
|
||||
if n <= 0: return str
|
||||
return ' '*((n+1)/2) + str + ' '*((n)/2)
|
||||
|
||||
# XXX The following code knows that print separates items with space!
|
||||
|
||||
# Print a single week (no newline)
|
||||
def prweek(week, width):
|
||||
for day in week:
|
||||
if day == 0: s = ''
|
||||
else: s = `day`
|
||||
print _center(s, width),
|
||||
"""Print a single week (no newline)."""
|
||||
for day in week:
|
||||
if day == 0: s = ''
|
||||
else: s = `day`
|
||||
print _center(s, width),
|
||||
|
||||
# Return a header for a week
|
||||
def weekheader(width):
|
||||
str = ''
|
||||
if width >= 9: names = day_name
|
||||
else: names = day_abbr
|
||||
for i in range(7):
|
||||
if str: str = str + ' '
|
||||
str = str + _center(names[i%7][:width], width)
|
||||
return str
|
||||
"""Return a header for a week."""
|
||||
str = ''
|
||||
if width >= 9: names = day_name
|
||||
else: names = day_abbr
|
||||
for i in range(7):
|
||||
if str: str = str + ' '
|
||||
str = str + _center(names[i%7][:width], width)
|
||||
return str
|
||||
|
||||
# Print a month's calendar
|
||||
def prmonth(year, month, w = 0, l = 0):
|
||||
w = max(2, w)
|
||||
l = max(1, l)
|
||||
print _center(month_name[month] + ' ' + `year`, 7*(w+1) - 1),
|
||||
print '\n'*l,
|
||||
print weekheader(w),
|
||||
print '\n'*l,
|
||||
for week in monthcalendar(year, month):
|
||||
prweek(week, w)
|
||||
print '\n'*l,
|
||||
"""Print a month's calendar."""
|
||||
w = max(2, w)
|
||||
l = max(1, l)
|
||||
print _center(month_name[month] + ' ' + `year`, 7*(w+1) - 1),
|
||||
print '\n'*l,
|
||||
print weekheader(w),
|
||||
print '\n'*l,
|
||||
for week in monthcalendar(year, month):
|
||||
prweek(week, w)
|
||||
print '\n'*l,
|
||||
|
||||
# Spacing of month columns
|
||||
_colwidth = 7*3 - 1 # Amount printed by prweek()
|
||||
_spacing = ' '*4 # Spaces between columns
|
||||
_colwidth = 7*3 - 1 # Amount printed by prweek()
|
||||
_spacing = ' '*4 # Spaces between columns
|
||||
|
||||
# 3-column formatting for year calendars
|
||||
def format3c(a, b, c):
|
||||
print _center(a, _colwidth),
|
||||
print _spacing,
|
||||
print _center(b, _colwidth),
|
||||
print _spacing,
|
||||
print _center(c, _colwidth)
|
||||
"""3-column formatting for year calendars"""
|
||||
print _center(a, _colwidth),
|
||||
print _spacing,
|
||||
print _center(b, _colwidth),
|
||||
print _spacing,
|
||||
print _center(c, _colwidth)
|
||||
|
||||
# Print a year's calendar
|
||||
def prcal(year):
|
||||
header = weekheader(2)
|
||||
format3c('', `year`, '')
|
||||
for q in range(January, January+12, 3):
|
||||
print
|
||||
format3c(month_name[q], month_name[q+1], month_name[q+2])
|
||||
format3c(header, header, header)
|
||||
data = []
|
||||
height = 0
|
||||
for month in range(q, q+3):
|
||||
cal = monthcalendar(year, month)
|
||||
if len(cal) > height: height = len(cal)
|
||||
data.append(cal)
|
||||
for i in range(height):
|
||||
for cal in data:
|
||||
if i >= len(cal):
|
||||
print ' '*_colwidth,
|
||||
else:
|
||||
prweek(cal[i], 2)
|
||||
print _spacing,
|
||||
print
|
||||
"""Print a year's calendar."""
|
||||
header = weekheader(2)
|
||||
format3c('', `year`, '')
|
||||
for q in range(January, January+12, 3):
|
||||
print
|
||||
format3c(month_name[q], month_name[q+1], month_name[q+2])
|
||||
format3c(header, header, header)
|
||||
data = []
|
||||
height = 0
|
||||
for month in range(q, q+3):
|
||||
cal = monthcalendar(year, month)
|
||||
if len(cal) > height: height = len(cal)
|
||||
data.append(cal)
|
||||
for i in range(height):
|
||||
for cal in data:
|
||||
if i >= len(cal):
|
||||
print ' '*_colwidth,
|
||||
else:
|
||||
prweek(cal[i], 2)
|
||||
print _spacing,
|
||||
print
|
||||
|
||||
# Unrelated but handy function to calculate Unix timestamp from GMT
|
||||
EPOCH = 1970
|
||||
def timegm(tuple):
|
||||
year, month, day, hour, minute, second = tuple[:6]
|
||||
assert year >= EPOCH
|
||||
assert 1 <= month <= 12
|
||||
days = 365*(year-EPOCH) + leapdays(EPOCH, year)
|
||||
for i in range(1, month):
|
||||
days = days + mdays[i]
|
||||
if month > 2 and isleap(year):
|
||||
days = days + 1
|
||||
days = days + day - 1
|
||||
hours = days*24 + hour
|
||||
minutes = hours*60 + minute
|
||||
seconds = minutes*60 + second
|
||||
return seconds
|
||||
"""Unrelated but handy function to calculate Unix timestamp from GMT."""
|
||||
year, month, day, hour, minute, second = tuple[:6]
|
||||
assert year >= EPOCH
|
||||
assert 1 <= month <= 12
|
||||
days = 365*(year-EPOCH) + leapdays(EPOCH, year)
|
||||
for i in range(1, month):
|
||||
days = days + mdays[i]
|
||||
if month > 2 and isleap(year):
|
||||
days = days + 1
|
||||
days = days + day - 1
|
||||
hours = days*24 + hour
|
||||
minutes = hours*60 + minute
|
||||
seconds = minutes*60 + second
|
||||
return seconds
|
||||
|
|
338
Lib/cmd.py
338
Lib/cmd.py
|
@ -1,39 +1,39 @@
|
|||
# A generic class to build line-oriented command interpreters
|
||||
#
|
||||
# Interpreters constructed with this class obey the following conventions:
|
||||
#
|
||||
# 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
|
||||
# of characters in the identchars member.
|
||||
# 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.
|
||||
# 4. Typing an empty line repeats the last command. (Actually, it calls the
|
||||
# method `emptyline', which may be overridden in a subclass.)
|
||||
# 5. There is a predefined `help' method. Given an argument `topic', it
|
||||
# calls the command `help_topic'. With no arguments, it lists all topics
|
||||
# with defined help_ functions, broken into up to three topics; documented
|
||||
# commands, miscellaneous help topics, and undocumented commands.
|
||||
# 6. The command '?' is a synonym for `help'. The command '!' is a synonym
|
||||
# for `shell', if a do_shell method exists.
|
||||
#
|
||||
# The `default' method may be overridden to intercept commands for which there
|
||||
# is no do_ method.
|
||||
#
|
||||
# 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 "=".
|
||||
#
|
||||
# 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
|
||||
# via an optional argument to the cmdloop() method.
|
||||
#
|
||||
# The data members `self.doc_header', `self.misc_header', and
|
||||
# `self.undoc_header' set the headers used for the help function's
|
||||
# listings of documented functions, miscellaneous topics, and undocumented
|
||||
# functions respectively.
|
||||
#
|
||||
# These interpreters use raw_input; thus, if the readline module is loaded,
|
||||
# they automatically support Emacs-like command history and editing features.
|
||||
#
|
||||
"""A generic class to build line-oriented command interpreters.
|
||||
|
||||
Interpreters constructed with this class obey the following conventions:
|
||||
|
||||
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
|
||||
of characters in the identchars member.
|
||||
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.
|
||||
4. Typing an empty line repeats the last command. (Actually, it calls the
|
||||
method `emptyline', which may be overridden in a subclass.)
|
||||
5. There is a predefined `help' method. Given an argument `topic', it
|
||||
calls the command `help_topic'. With no arguments, it lists all topics
|
||||
with defined help_ functions, broken into up to three topics; documented
|
||||
commands, miscellaneous help topics, and undocumented commands.
|
||||
6. The command '?' is a synonym for `help'. The command '!' is a synonym
|
||||
for `shell', if a do_shell method exists.
|
||||
|
||||
The `default' method may be overridden to intercept commands for which there
|
||||
is no do_ method.
|
||||
|
||||
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 "=".
|
||||
|
||||
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
|
||||
via an optional argument to the cmdloop() method.
|
||||
|
||||
The data members `self.doc_header', `self.misc_header', and
|
||||
`self.undoc_header' set the headers used for the help function's
|
||||
listings of documented functions, miscellaneous topics, and undocumented
|
||||
functions respectively.
|
||||
|
||||
These interpreters use raw_input; thus, if the readline module is loaded,
|
||||
they automatically support Emacs-like command history and editing features.
|
||||
"""
|
||||
|
||||
import string
|
||||
|
||||
|
@ -41,147 +41,147 @@ PROMPT = '(Cmd) '
|
|||
IDENTCHARS = string.letters + string.digits + '_'
|
||||
|
||||
class Cmd:
|
||||
prompt = PROMPT
|
||||
identchars = IDENTCHARS
|
||||
ruler = '='
|
||||
lastcmd = ''
|
||||
cmdqueue = []
|
||||
intro = None
|
||||
doc_leader = ""
|
||||
doc_header = "Documented commands (type help <topic>):"
|
||||
misc_header = "Miscellaneous help topics:"
|
||||
undoc_header = "Undocumented commands:"
|
||||
nohelp = "*** No help on %s"
|
||||
prompt = PROMPT
|
||||
identchars = IDENTCHARS
|
||||
ruler = '='
|
||||
lastcmd = ''
|
||||
cmdqueue = []
|
||||
intro = None
|
||||
doc_leader = ""
|
||||
doc_header = "Documented commands (type help <topic>):"
|
||||
misc_header = "Miscellaneous help topics:"
|
||||
undoc_header = "Undocumented commands:"
|
||||
nohelp = "*** No help on %s"
|
||||
|
||||
def __init__(self): pass
|
||||
def __init__(self): pass
|
||||
|
||||
def cmdloop(self, intro=None):
|
||||
self.preloop()
|
||||
if intro != None:
|
||||
self.intro = intro
|
||||
if self.intro:
|
||||
print self.intro
|
||||
stop = None
|
||||
while not stop:
|
||||
if self.cmdqueue:
|
||||
line = self.cmdqueue[0]
|
||||
del self.cmdqueue[0]
|
||||
else:
|
||||
try:
|
||||
line = raw_input(self.prompt)
|
||||
except EOFError:
|
||||
line = 'EOF'
|
||||
line = self.precmd(line)
|
||||
stop = self.onecmd(line)
|
||||
stop = self.postcmd(stop, line)
|
||||
self.postloop()
|
||||
def cmdloop(self, intro=None):
|
||||
self.preloop()
|
||||
if intro != None:
|
||||
self.intro = intro
|
||||
if self.intro:
|
||||
print self.intro
|
||||
stop = None
|
||||
while not stop:
|
||||
if self.cmdqueue:
|
||||
line = self.cmdqueue[0]
|
||||
del self.cmdqueue[0]
|
||||
else:
|
||||
try:
|
||||
line = raw_input(self.prompt)
|
||||
except EOFError:
|
||||
line = 'EOF'
|
||||
line = self.precmd(line)
|
||||
stop = self.onecmd(line)
|
||||
stop = self.postcmd(stop, line)
|
||||
self.postloop()
|
||||
|
||||
def precmd(self, line):
|
||||
return line
|
||||
def precmd(self, line):
|
||||
return line
|
||||
|
||||
def postcmd(self, stop, line):
|
||||
return stop
|
||||
def postcmd(self, stop, line):
|
||||
return stop
|
||||
|
||||
def preloop(self):
|
||||
pass
|
||||
def preloop(self):
|
||||
pass
|
||||
|
||||
def postloop(self):
|
||||
pass
|
||||
def postloop(self):
|
||||
pass
|
||||
|
||||
def onecmd(self, line):
|
||||
line = string.strip(line)
|
||||
if line == '?':
|
||||
line = 'help'
|
||||
elif line == '!':
|
||||
if hasattr(self, 'do_shell'):
|
||||
line = 'shell'
|
||||
else:
|
||||
return self.default(line)
|
||||
elif not line:
|
||||
return self.emptyline()
|
||||
self.lastcmd = line
|
||||
i, n = 0, len(line)
|
||||
while i < n and line[i] in self.identchars: i = i+1
|
||||
cmd, arg = line[:i], string.strip(line[i:])
|
||||
if cmd == '':
|
||||
return self.default(line)
|
||||
else:
|
||||
try:
|
||||
func = getattr(self, 'do_' + cmd)
|
||||
except AttributeError:
|
||||
return self.default(line)
|
||||
return func(arg)
|
||||
def onecmd(self, line):
|
||||
line = string.strip(line)
|
||||
if line == '?':
|
||||
line = 'help'
|
||||
elif line == '!':
|
||||
if hasattr(self, 'do_shell'):
|
||||
line = 'shell'
|
||||
else:
|
||||
return self.default(line)
|
||||
elif not line:
|
||||
return self.emptyline()
|
||||
self.lastcmd = line
|
||||
i, n = 0, len(line)
|
||||
while i < n and line[i] in self.identchars: i = i+1
|
||||
cmd, arg = line[:i], string.strip(line[i:])
|
||||
if cmd == '':
|
||||
return self.default(line)
|
||||
else:
|
||||
try:
|
||||
func = getattr(self, 'do_' + cmd)
|
||||
except AttributeError:
|
||||
return self.default(line)
|
||||
return func(arg)
|
||||
|
||||
def emptyline(self):
|
||||
if self.lastcmd:
|
||||
return self.onecmd(self.lastcmd)
|
||||
def emptyline(self):
|
||||
if self.lastcmd:
|
||||
return self.onecmd(self.lastcmd)
|
||||
|
||||
def default(self, line):
|
||||
print '*** Unknown syntax:', line
|
||||
def default(self, line):
|
||||
print '*** Unknown syntax:', line
|
||||
|
||||
def do_help(self, arg):
|
||||
if arg:
|
||||
# XXX check arg syntax
|
||||
try:
|
||||
func = getattr(self, 'help_' + arg)
|
||||
except:
|
||||
try:
|
||||
doc=getattr(self, 'do_' + arg).__doc__
|
||||
if doc:
|
||||
print doc
|
||||
return
|
||||
except:
|
||||
pass
|
||||
print self.nohelp % (arg,)
|
||||
return
|
||||
func()
|
||||
else:
|
||||
# Inheritance says we have to look in class and
|
||||
# base classes; order is not important.
|
||||
names = []
|
||||
classes = [self.__class__]
|
||||
while classes:
|
||||
aclass = classes[0]
|
||||
if aclass.__bases__:
|
||||
classes = classes + list(aclass.__bases__)
|
||||
names = names + dir(aclass)
|
||||
del classes[0]
|
||||
cmds_doc = []
|
||||
cmds_undoc = []
|
||||
help = {}
|
||||
for name in names:
|
||||
if name[:5] == 'help_':
|
||||
help[name[5:]]=1
|
||||
names.sort()
|
||||
# There can be duplicates if routines overridden
|
||||
prevname = ''
|
||||
for name in names:
|
||||
if name[:3] == 'do_':
|
||||
if name == prevname:
|
||||
continue
|
||||
prevname = name
|
||||
cmd=name[3:]
|
||||
if help.has_key(cmd):
|
||||
cmds_doc.append(cmd)
|
||||
del help[cmd]
|
||||
elif getattr(self, name).__doc__:
|
||||
cmds_doc.append(cmd)
|
||||
else:
|
||||
cmds_undoc.append(cmd)
|
||||
print self.doc_leader
|
||||
self.print_topics(self.doc_header, cmds_doc, 15,80)
|
||||
self.print_topics(self.misc_header, help.keys(),15,80)
|
||||
self.print_topics(self.undoc_header, cmds_undoc, 15,80)
|
||||
def do_help(self, arg):
|
||||
if arg:
|
||||
# XXX check arg syntax
|
||||
try:
|
||||
func = getattr(self, 'help_' + arg)
|
||||
except:
|
||||
try:
|
||||
doc=getattr(self, 'do_' + arg).__doc__
|
||||
if doc:
|
||||
print doc
|
||||
return
|
||||
except:
|
||||
pass
|
||||
print self.nohelp % (arg,)
|
||||
return
|
||||
func()
|
||||
else:
|
||||
# Inheritance says we have to look in class and
|
||||
# base classes; order is not important.
|
||||
names = []
|
||||
classes = [self.__class__]
|
||||
while classes:
|
||||
aclass = classes[0]
|
||||
if aclass.__bases__:
|
||||
classes = classes + list(aclass.__bases__)
|
||||
names = names + dir(aclass)
|
||||
del classes[0]
|
||||
cmds_doc = []
|
||||
cmds_undoc = []
|
||||
help = {}
|
||||
for name in names:
|
||||
if name[:5] == 'help_':
|
||||
help[name[5:]]=1
|
||||
names.sort()
|
||||
# There can be duplicates if routines overridden
|
||||
prevname = ''
|
||||
for name in names:
|
||||
if name[:3] == 'do_':
|
||||
if name == prevname:
|
||||
continue
|
||||
prevname = name
|
||||
cmd=name[3:]
|
||||
if help.has_key(cmd):
|
||||
cmds_doc.append(cmd)
|
||||
del help[cmd]
|
||||
elif getattr(self, name).__doc__:
|
||||
cmds_doc.append(cmd)
|
||||
else:
|
||||
cmds_undoc.append(cmd)
|
||||
print self.doc_leader
|
||||
self.print_topics(self.doc_header, cmds_doc, 15,80)
|
||||
self.print_topics(self.misc_header, help.keys(),15,80)
|
||||
self.print_topics(self.undoc_header, cmds_undoc, 15,80)
|
||||
|
||||
def print_topics(self, header, cmds, cmdlen, maxcol):
|
||||
if cmds:
|
||||
print header;
|
||||
if self.ruler:
|
||||
print self.ruler * len(header)
|
||||
(cmds_per_line,junk)=divmod(maxcol,cmdlen)
|
||||
col=cmds_per_line
|
||||
for cmd in cmds:
|
||||
if col==0: print
|
||||
print (("%-"+`cmdlen`+"s") % cmd),
|
||||
col = (col+1) % cmds_per_line
|
||||
print "\n"
|
||||
def print_topics(self, header, cmds, cmdlen, maxcol):
|
||||
if cmds:
|
||||
print header;
|
||||
if self.ruler:
|
||||
print self.ruler * len(header)
|
||||
(cmds_per_line,junk)=divmod(maxcol,cmdlen)
|
||||
col=cmds_per_line
|
||||
for cmd in cmds:
|
||||
if col==0: print
|
||||
print (("%-"+`cmdlen`+"s") % cmd),
|
||||
col = (col+1) % cmds_per_line
|
||||
print "\n"
|
||||
|
|
108
Lib/cmp.py
108
Lib/cmp.py
|
@ -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
|
||||
# - Files with different type or size cannot be identical
|
||||
# - We keep a cache of outcomes of earlier comparisons
|
||||
# - We don't fork a process to run 'cmp' but read the files ourselves
|
||||
Tricks (used in this order):
|
||||
- Files with identical type, size & mtime are assumed to be clones
|
||||
- Files with different type or size cannot be identical
|
||||
- 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
|
||||
|
||||
cache = {}
|
||||
|
||||
def cmp(f1, f2, shallow=1): # Compare two files, use the cache if possible.
|
||||
# Return 1 for identical files, 0 for different.
|
||||
# Raise exceptions if either file could not be statted, read, etc.
|
||||
s1, s2 = sig(os.stat(f1)), sig(os.stat(f2))
|
||||
if s1[0] <> 8 or s2[0] <> 8:
|
||||
# Either is a not a plain file -- always report as different
|
||||
return 0
|
||||
if shallow and s1 == s2:
|
||||
# type, size & mtime match -- report same
|
||||
return 1
|
||||
if s1[:2] <> s2[:2]: # Types or sizes differ, don't bother
|
||||
# types or sizes differ -- report different
|
||||
return 0
|
||||
# same type and size -- look in the cache
|
||||
key = (f1, f2)
|
||||
try:
|
||||
cs1, cs2, outcome = cache[key]
|
||||
# cache hit
|
||||
if s1 == cs1 and s2 == cs2:
|
||||
# cached signatures match
|
||||
return outcome
|
||||
# stale cached signature(s)
|
||||
except KeyError:
|
||||
# cache miss
|
||||
pass
|
||||
# really compare
|
||||
outcome = do_cmp(f1, f2)
|
||||
cache[key] = s1, s2, outcome
|
||||
return outcome
|
||||
def cmp(f1, f2, shallow=1):
|
||||
"""Compare two files, use the cache if possible.
|
||||
Return 1 for identical files, 0 for different.
|
||||
Raise exceptions if either file could not be statted, read, etc."""
|
||||
s1, s2 = sig(os.stat(f1)), sig(os.stat(f2))
|
||||
if s1[0] <> 8 or s2[0] <> 8:
|
||||
# Either is a not a plain file -- always report as different
|
||||
return 0
|
||||
if shallow and s1 == s2:
|
||||
# type, size & mtime match -- report same
|
||||
return 1
|
||||
if s1[:2] <> s2[:2]: # Types or sizes differ, don't bother
|
||||
# types or sizes differ -- report different
|
||||
return 0
|
||||
# same type and size -- look in the cache
|
||||
key = (f1, f2)
|
||||
try:
|
||||
cs1, cs2, outcome = cache[key]
|
||||
# cache hit
|
||||
if s1 == cs1 and s2 == cs2:
|
||||
# cached signatures match
|
||||
return outcome
|
||||
# stale cached signature(s)
|
||||
except KeyError:
|
||||
# cache miss
|
||||
pass
|
||||
# really compare
|
||||
outcome = do_cmp(f1, f2)
|
||||
cache[key] = s1, s2, outcome
|
||||
return outcome
|
||||
|
||||
def sig(st): # Return signature (i.e., type, size, mtime) from raw stat data
|
||||
# 0-5: st_mode, st_ino, st_dev, st_nlink, st_uid, st_gid
|
||||
# 6-9: st_size, st_atime, st_mtime, st_ctime
|
||||
type = st[0] / 4096
|
||||
size = st[6]
|
||||
mtime = st[8]
|
||||
return type, size, mtime
|
||||
def sig(st):
|
||||
"""Return signature (i.e., type, size, mtime) from raw stat data
|
||||
0-5: st_mode, st_ino, st_dev, st_nlink, st_uid, st_gid
|
||||
6-9: st_size, st_atime, st_mtime, st_ctime"""
|
||||
type = st[0] / 4096
|
||||
size = st[6]
|
||||
mtime = st[8]
|
||||
return type, size, mtime
|
||||
|
||||
def do_cmp(f1, f2): # Compare two files, really
|
||||
bufsize = 8*1024 # Could be tuned
|
||||
fp1 = open(f1, 'rb')
|
||||
fp2 = open(f2, 'rb')
|
||||
while 1:
|
||||
b1 = fp1.read(bufsize)
|
||||
b2 = fp2.read(bufsize)
|
||||
if b1 <> b2: return 0
|
||||
if not b1: return 1
|
||||
def do_cmp(f1, f2):
|
||||
"""Compare two files, really."""
|
||||
bufsize = 8*1024 # Could be tuned
|
||||
fp1 = open(f1, 'rb')
|
||||
fp2 = open(f2, 'rb')
|
||||
while 1:
|
||||
b1 = fp1.read(bufsize)
|
||||
b2 = fp2.read(bufsize)
|
||||
if b1 <> b2: return 0
|
||||
if not b1: return 1
|
||||
|
|
100
Lib/cmpcache.py
100
Lib/cmpcache.py
|
@ -1,13 +1,12 @@
|
|||
# Module 'cmpcache'
|
||||
#
|
||||
# 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
|
||||
# - Files with identical type, size & mtime are assumed to be clones
|
||||
# - Files with different type or size cannot be identical
|
||||
# - We keep a cache of outcomes of earlier comparisons
|
||||
# - We don't fork a process to run 'cmp' but read the files ourselves
|
||||
"""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
|
||||
- Files with identical type, size & mtime are assumed to be clones
|
||||
- Files with different type or size cannot be identical
|
||||
- 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
|
||||
from stat import *
|
||||
|
@ -19,50 +18,47 @@ import statcache
|
|||
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):
|
||||
# Return 1 for identical files, 0 for different.
|
||||
# Raise exceptions if either file could not be statted, read, etc.
|
||||
s1, s2 = sig(statcache.stat(f1)), sig(statcache.stat(f2))
|
||||
if not S_ISREG(s1[0]) or not S_ISREG(s2[0]):
|
||||
# Either is a not a plain file -- always report as different
|
||||
return 0
|
||||
if shallow and s1 == s2:
|
||||
# type, size & mtime match -- report same
|
||||
return 1
|
||||
if s1[:2] <> s2[:2]: # Types or sizes differ, don't bother
|
||||
# types or sizes differ -- report different
|
||||
return 0
|
||||
# same type and size -- look in the cache
|
||||
key = f1 + ' ' + f2
|
||||
if cache.has_key(key):
|
||||
cs1, cs2, outcome = cache[key]
|
||||
# cache hit
|
||||
if s1 == cs1 and s2 == cs2:
|
||||
# cached signatures match
|
||||
return outcome
|
||||
# stale cached signature(s)
|
||||
# really compare
|
||||
outcome = do_cmp(f1, f2)
|
||||
cache[key] = s1, s2, outcome
|
||||
return outcome
|
||||
"""Compare two files, use the cache if possible.
|
||||
May raise os.error if a stat or open of either fails.
|
||||
Return 1 for identical files, 0 for different.
|
||||
Raise exceptions if either file could not be statted, read, etc."""
|
||||
s1, s2 = sig(statcache.stat(f1)), sig(statcache.stat(f2))
|
||||
if not S_ISREG(s1[0]) or not S_ISREG(s2[0]):
|
||||
# Either is a not a plain file -- always report as different
|
||||
return 0
|
||||
if shallow and s1 == s2:
|
||||
# type, size & mtime match -- report same
|
||||
return 1
|
||||
if s1[:2] <> s2[:2]: # Types or sizes differ, don't bother
|
||||
# types or sizes differ -- report different
|
||||
return 0
|
||||
# same type and size -- look in the cache
|
||||
key = f1 + ' ' + f2
|
||||
if cache.has_key(key):
|
||||
cs1, cs2, outcome = cache[key]
|
||||
# cache hit
|
||||
if s1 == cs1 and s2 == cs2:
|
||||
# cached signatures match
|
||||
return outcome
|
||||
# stale cached signature(s)
|
||||
# really compare
|
||||
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):
|
||||
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):
|
||||
#print ' cmp', f1, f2 # XXX remove when debugged
|
||||
bufsize = 8*1024 # Could be tuned
|
||||
fp1 = open(f1, 'rb')
|
||||
fp2 = open(f2, 'rb')
|
||||
while 1:
|
||||
b1 = fp1.read(bufsize)
|
||||
b2 = fp2.read(bufsize)
|
||||
if b1 <> b2: return 0
|
||||
if not b1: return 1
|
||||
"""Compare two files, really."""
|
||||
#print ' cmp', f1, f2 # XXX remove when debugged
|
||||
bufsize = 8*1024 # Could be tuned
|
||||
fp1 = open(f1, 'rb')
|
||||
fp2 = open(f2, 'rb')
|
||||
while 1:
|
||||
b1 = fp1.read(bufsize)
|
||||
b2 = fp2.read(bufsize)
|
||||
if b1 <> b2: return 0
|
||||
if not b1: return 1
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Helper to provide extensibility for pickle/cPickle.
|
||||
"""Helper to provide extensibility for pickle/cPickle."""
|
||||
|
||||
dispatch_table = {}
|
||||
safe_constructors = {}
|
||||
|
|
|
@ -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.
|
||||
# Also contains a subroutine to append slashes to directories.
|
||||
"""Return a sorted list of the files in a directory, using a cache
|
||||
to avoid reading the directory more often than necessary.
|
||||
Also contains a subroutine to append slashes to directories."""
|
||||
|
||||
import os
|
||||
|
||||
cache = {}
|
||||
|
||||
def listdir(path): # List directory contents, using cache
|
||||
try:
|
||||
cached_mtime, list = cache[path]
|
||||
del cache[path]
|
||||
except KeyError:
|
||||
cached_mtime, list = -1, []
|
||||
try:
|
||||
mtime = os.stat(path)[8]
|
||||
except os.error:
|
||||
return []
|
||||
if mtime <> cached_mtime:
|
||||
try:
|
||||
list = os.listdir(path)
|
||||
except os.error:
|
||||
return []
|
||||
list.sort()
|
||||
cache[path] = mtime, list
|
||||
return list
|
||||
def listdir(path):
|
||||
"""List directory contents, using cache."""
|
||||
try:
|
||||
cached_mtime, list = cache[path]
|
||||
del cache[path]
|
||||
except KeyError:
|
||||
cached_mtime, list = -1, []
|
||||
try:
|
||||
mtime = os.stat(path)[8]
|
||||
except os.error:
|
||||
return []
|
||||
if mtime <> cached_mtime:
|
||||
try:
|
||||
list = os.listdir(path)
|
||||
except os.error:
|
||||
return []
|
||||
list.sort()
|
||||
cache[path] = mtime, list
|
||||
return list
|
||||
|
||||
opendir = listdir # XXX backward compatibility
|
||||
|
||||
def annotate(head, list): # Add '/' suffixes to directories
|
||||
for i in range(len(list)):
|
||||
if os.path.isdir(os.path.join(head, list[i])):
|
||||
list[i] = list[i] + '/'
|
||||
def annotate(head, list):
|
||||
"""Add '/' suffixes to directories."""
|
||||
for i in range(len(list)):
|
||||
if os.path.isdir(os.path.join(head, list[i])):
|
||||
list[i] = list[i] + '/'
|
||||
|
|
360
Lib/dircmp.py
360
Lib/dircmp.py
|
@ -1,6 +1,4 @@
|
|||
# Module 'dirmp'
|
||||
#
|
||||
# Defines a class to build directory diff tools on.
|
||||
"""A class to build directory diff tools on."""
|
||||
|
||||
import os
|
||||
|
||||
|
@ -9,195 +7,195 @@ import cmpcache
|
|||
import statcache
|
||||
from stat import *
|
||||
|
||||
# Directory comparison class.
|
||||
#
|
||||
class dircmp:
|
||||
#
|
||||
def new(self, a, b): # Initialize
|
||||
self.a = a
|
||||
self.b = b
|
||||
# Properties that caller may change before calling self.run():
|
||||
self.hide = [os.curdir, os.pardir] # Names never to be shown
|
||||
self.ignore = ['RCS', 'tags'] # Names ignored in comparison
|
||||
#
|
||||
return self
|
||||
#
|
||||
def run(self): # Compare everything except common subdirectories
|
||||
self.a_list = filter(dircache.listdir(self.a), self.hide)
|
||||
self.b_list = filter(dircache.listdir(self.b), self.hide)
|
||||
self.a_list.sort()
|
||||
self.b_list.sort()
|
||||
self.phase1()
|
||||
self.phase2()
|
||||
self.phase3()
|
||||
#
|
||||
def phase1(self): # Compute common names
|
||||
self.a_only = []
|
||||
self.common = []
|
||||
for x in self.a_list:
|
||||
if x in self.b_list:
|
||||
self.common.append(x)
|
||||
else:
|
||||
self.a_only.append(x)
|
||||
#
|
||||
self.b_only = []
|
||||
for x in self.b_list:
|
||||
if x not in self.common:
|
||||
self.b_only.append(x)
|
||||
#
|
||||
def phase2(self): # Distinguish files, directories, funnies
|
||||
self.common_dirs = []
|
||||
self.common_files = []
|
||||
self.common_funny = []
|
||||
#
|
||||
for x in self.common:
|
||||
a_path = os.path.join(self.a, x)
|
||||
b_path = os.path.join(self.b, x)
|
||||
#
|
||||
ok = 1
|
||||
try:
|
||||
a_stat = statcache.stat(a_path)
|
||||
except os.error, why:
|
||||
# print 'Can\'t stat', a_path, ':', why[1]
|
||||
ok = 0
|
||||
try:
|
||||
b_stat = statcache.stat(b_path)
|
||||
except os.error, why:
|
||||
# print 'Can\'t stat', b_path, ':', why[1]
|
||||
ok = 0
|
||||
#
|
||||
if ok:
|
||||
a_type = S_IFMT(a_stat[ST_MODE])
|
||||
b_type = S_IFMT(b_stat[ST_MODE])
|
||||
if a_type <> b_type:
|
||||
self.common_funny.append(x)
|
||||
elif S_ISDIR(a_type):
|
||||
self.common_dirs.append(x)
|
||||
elif S_ISREG(a_type):
|
||||
self.common_files.append(x)
|
||||
else:
|
||||
self.common_funny.append(x)
|
||||
else:
|
||||
self.common_funny.append(x)
|
||||
#
|
||||
def phase3(self): # Find out differences between common files
|
||||
xx = cmpfiles(self.a, self.b, self.common_files)
|
||||
self.same_files, self.diff_files, self.funny_files = xx
|
||||
#
|
||||
def phase4(self): # Find out differences between common subdirectories
|
||||
# A new dircmp object is created for each common subdirectory,
|
||||
# these are stored in a dictionary indexed by filename.
|
||||
# The hide and ignore properties are inherited from the parent
|
||||
self.subdirs = {}
|
||||
for x in self.common_dirs:
|
||||
a_x = os.path.join(self.a, x)
|
||||
b_x = os.path.join(self.b, x)
|
||||
self.subdirs[x] = newdd = dircmp().new(a_x, b_x)
|
||||
newdd.hide = self.hide
|
||||
newdd.ignore = self.ignore
|
||||
newdd.run()
|
||||
#
|
||||
def phase4_closure(self): # Recursively call phase4() on subdirectories
|
||||
self.phase4()
|
||||
for x in self.subdirs.keys():
|
||||
self.subdirs[x].phase4_closure()
|
||||
#
|
||||
def report(self): # Print a report on the differences between a and b
|
||||
# Assume that phases 1 to 3 have been executed
|
||||
# Output format is purposely lousy
|
||||
print 'diff', self.a, self.b
|
||||
if self.a_only:
|
||||
print 'Only in', self.a, ':', self.a_only
|
||||
if self.b_only:
|
||||
print 'Only in', self.b, ':', self.b_only
|
||||
if self.same_files:
|
||||
print 'Identical files :', self.same_files
|
||||
if self.diff_files:
|
||||
print 'Differing files :', self.diff_files
|
||||
if self.funny_files:
|
||||
print 'Trouble with common files :', self.funny_files
|
||||
if self.common_dirs:
|
||||
print 'Common subdirectories :', self.common_dirs
|
||||
if self.common_funny:
|
||||
print 'Common funny cases :', self.common_funny
|
||||
#
|
||||
def report_closure(self): # Print reports on self and on subdirs
|
||||
# If phase 4 hasn't been done, no subdir reports are printed
|
||||
self.report()
|
||||
try:
|
||||
x = self.subdirs
|
||||
except AttributeError:
|
||||
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()
|
||||
"""Directory comparison class."""
|
||||
|
||||
def new(self, a, b):
|
||||
"""Initialize."""
|
||||
self.a = a
|
||||
self.b = b
|
||||
# Properties that caller may change before calling self.run():
|
||||
self.hide = [os.curdir, os.pardir] # Names never to be shown
|
||||
self.ignore = ['RCS', 'tags'] # Names ignored in comparison
|
||||
|
||||
return self
|
||||
|
||||
def run(self):
|
||||
"""Compare everything except common subdirectories."""
|
||||
self.a_list = filter(dircache.listdir(self.a), self.hide)
|
||||
self.b_list = filter(dircache.listdir(self.b), self.hide)
|
||||
self.a_list.sort()
|
||||
self.b_list.sort()
|
||||
self.phase1()
|
||||
self.phase2()
|
||||
self.phase3()
|
||||
|
||||
def phase1(self):
|
||||
"""Compute common names."""
|
||||
self.a_only = []
|
||||
self.common = []
|
||||
for x in self.a_list:
|
||||
if x in self.b_list:
|
||||
self.common.append(x)
|
||||
else:
|
||||
self.a_only.append(x)
|
||||
|
||||
self.b_only = []
|
||||
for x in self.b_list:
|
||||
if x not in self.common:
|
||||
self.b_only.append(x)
|
||||
|
||||
def phase2(self):
|
||||
"""Distinguish files, directories, funnies."""
|
||||
self.common_dirs = []
|
||||
self.common_files = []
|
||||
self.common_funny = []
|
||||
|
||||
for x in self.common:
|
||||
a_path = os.path.join(self.a, x)
|
||||
b_path = os.path.join(self.b, x)
|
||||
|
||||
ok = 1
|
||||
try:
|
||||
a_stat = statcache.stat(a_path)
|
||||
except os.error, why:
|
||||
# print 'Can\'t stat', a_path, ':', why[1]
|
||||
ok = 0
|
||||
try:
|
||||
b_stat = statcache.stat(b_path)
|
||||
except os.error, why:
|
||||
# print 'Can\'t stat', b_path, ':', why[1]
|
||||
ok = 0
|
||||
|
||||
if ok:
|
||||
a_type = S_IFMT(a_stat[ST_MODE])
|
||||
b_type = S_IFMT(b_stat[ST_MODE])
|
||||
if a_type <> b_type:
|
||||
self.common_funny.append(x)
|
||||
elif S_ISDIR(a_type):
|
||||
self.common_dirs.append(x)
|
||||
elif S_ISREG(a_type):
|
||||
self.common_files.append(x)
|
||||
else:
|
||||
self.common_funny.append(x)
|
||||
else:
|
||||
self.common_funny.append(x)
|
||||
|
||||
def phase3(self):
|
||||
"""Find out differences between common files."""
|
||||
xx = cmpfiles(self.a, self.b, self.common_files)
|
||||
self.same_files, self.diff_files, self.funny_files = xx
|
||||
|
||||
def phase4(self):
|
||||
"""Find out differences between common subdirectories.
|
||||
A new dircmp object is created for each common subdirectory,
|
||||
these are stored in a dictionary indexed by filename.
|
||||
The hide and ignore properties are inherited from the parent."""
|
||||
self.subdirs = {}
|
||||
for x in self.common_dirs:
|
||||
a_x = os.path.join(self.a, x)
|
||||
b_x = os.path.join(self.b, x)
|
||||
self.subdirs[x] = newdd = dircmp().new(a_x, b_x)
|
||||
newdd.hide = self.hide
|
||||
newdd.ignore = self.ignore
|
||||
newdd.run()
|
||||
|
||||
def phase4_closure(self):
|
||||
"""Recursively call phase4() on subdirectories."""
|
||||
self.phase4()
|
||||
for x in self.subdirs.keys():
|
||||
self.subdirs[x].phase4_closure()
|
||||
|
||||
def report(self):
|
||||
"""Print a report on the differences between a and b."""
|
||||
# Assume that phases 1 to 3 have been executed
|
||||
# Output format is purposely lousy
|
||||
print 'diff', self.a, self.b
|
||||
if self.a_only:
|
||||
print 'Only in', self.a, ':', self.a_only
|
||||
if self.b_only:
|
||||
print 'Only in', self.b, ':', self.b_only
|
||||
if self.same_files:
|
||||
print 'Identical files :', self.same_files
|
||||
if self.diff_files:
|
||||
print 'Differing files :', self.diff_files
|
||||
if self.funny_files:
|
||||
print 'Trouble with common files :', self.funny_files
|
||||
if self.common_dirs:
|
||||
print 'Common subdirectories :', self.common_dirs
|
||||
if self.common_funny:
|
||||
print 'Common funny cases :', self.common_funny
|
||||
|
||||
def report_closure(self):
|
||||
"""Print reports on self and on subdirs.
|
||||
If phase 4 hasn't been done, no subdir reports are printed."""
|
||||
self.report()
|
||||
try:
|
||||
x = self.subdirs
|
||||
except AttributeError:
|
||||
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):
|
||||
res = ([], [], [])
|
||||
for x in common:
|
||||
res[cmp(os.path.join(a, x), os.path.join(b, x))].append(x)
|
||||
return res
|
||||
"""Compare common files in two directories.
|
||||
Return:
|
||||
- files that compare equal
|
||||
- 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):
|
||||
try:
|
||||
if cmpcache.cmp(a, b): return 0
|
||||
return 1
|
||||
except os.error:
|
||||
return 2
|
||||
"""Compare two files.
|
||||
Return:
|
||||
0 for equal
|
||||
1 for different
|
||||
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):
|
||||
result = []
|
||||
for item in list:
|
||||
if item not in skip: result.append(item)
|
||||
return result
|
||||
"""Return a copy with items that occur in skip removed."""
|
||||
|
||||
result = []
|
||||
for item in list:
|
||||
if item not in skip: result.append(item)
|
||||
return result
|
||||
|
||||
|
||||
# Demonstration and testing.
|
||||
#
|
||||
def 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()
|
||||
"""Demonstration and testing."""
|
||||
|
||||
# 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()
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
# General floating point formatting functions.
|
||||
"""General floating point formatting functions.
|
||||
|
||||
# Functions:
|
||||
# fix(x, digits_behind)
|
||||
# sci(x, digits_behind)
|
||||
Functions:
|
||||
fix(x, digits_behind)
|
||||
sci(x, digits_behind)
|
||||
|
||||
# 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
|
||||
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
|
||||
"""
|
||||
|
||||
import re
|
||||
|
||||
|
|
Loading…
Reference in New Issue