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
|
# 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.
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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):
|
||||||
|
@ -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):
|
||||||
|
1717
Lib/aifc.py
1717
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'
|
error = 'audiodev.error'
|
||||||
|
|
||||||
class Play_Audio_sgi:
|
class Play_Audio_sgi:
|
||||||
|
112
Lib/base64.py
112
Lib/base64.py
@ -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
1008
Lib/bdb.py
File diff suppressed because it is too large
Load Diff
887
Lib/binhex.py
887
Lib/binhex.py
@ -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()
|
||||||
|
@ -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
|
||||||
|
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
|
# 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
|
||||||
|
338
Lib/cmd.py
338
Lib/cmd.py
@ -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"
|
||||||
|
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
|
||||||
# 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
|
||||||
|
100
Lib/cmpcache.py
100
Lib/cmpcache.py
@ -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
|
||||||
|
@ -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 = {}
|
||||||
|
@ -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] + '/'
|
||||||
|
360
Lib/dircmp.py
360
Lib/dircmp.py
@ -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()
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user