More trivial comment -> docstring transformations by Ka-Ping Yee,

who writes:

Here is batch 2, as a big collection of CVS context diffs.
Along with moving comments into docstrings, i've added a
couple of missing docstrings and attempted to make sure more
module docstrings begin with a one-line summary.

I did not add docstrings to the methods in profile.py for
fear of upsetting any careful optimizations there, though
i did move class documentation into class docstrings.

The convention i'm using is to leave credits/version/copyright
type of stuff in # comments, and move the rest of the descriptive
stuff about module usage into module docstrings.  Hope this is
okay.
This commit is contained in:
Guido van Rossum
2000-02-04 15:10:34 +00:00
parent 8b6323d3ef
commit 54f22ed30b
30 changed files with 1547 additions and 1792 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,318 +1,57 @@
"""Utilities for comparing files and directories.
"""Compare files."""
Classes:
dircmp
Functions:
cmp(f1, f2, shallow=1, use_statcache=0) -> int
cmpfiles(a, b, common) -> ([], [], [])
"""
import os
import stat
import statcache
import os, stat, statcache
_cache = {}
BUFSIZE=8*1024
def cmp(f1, f2, shallow=1,use_statcache=0):
"""Compare two files.
def cmp(f1, f2, shallow=1,use_statcache=0):
"""Compare two files.
Arguments:
Arguments:
f1 -- First file name
f1 -- First file name
f2 -- Second file name
f2 -- Second file name
shallow -- Just check stat signature (do not read the files).
defaults to 1.
shallow -- Just check stat signature (do not read the files).
defaults to 1.
use_statcache -- Do not stat() each file directly: go through
the statcache module for more efficiency.
use_statcache -- Do not stat() each file directly: go through
the statcache module for more efficiency.
Return value:
Return value:
integer -- 1 if the files are the same, 0 otherwise.
integer -- 1 if the files are the same, 0 otherwise.
This function uses a cache for past comparisons and the results,
with a cache invalidation mechanism relying on stale signatures.
Of course, if 'use_statcache' is true, this mechanism is defeated,
and the cache will never grow stale.
This function uses a cache for past comparisons and the results,
with a cache invalidation mechanism relying on stale signatures.
Of course, if 'use_statcache' is true, this mechanism is defeated,
and the cache will never grow stale.
"""
stat_function = (os.stat, statcache.stat)[use_statcache]
s1, s2 = _sig(stat_function(f1)), _sig(stat_function(f2))
if s1[0]!=stat.S_IFREG or s2[0]!=stat.S_IFREG: return 0
if shallow and s1 == s2: return 1
if s1[1]!=s2[1]: return 0
"""
stat_function = (os.stat, statcache.stat)[use_statcache]
s1, s2 = _sig(stat_function(f1)), _sig(stat_function(f2))
if s1[0]!=stat.S_IFREG or s2[0]!=stat.S_IFREG: return 0
if shallow and s1 == s2: return 1
if s1[1]!=s2[1]: return 0
result = _cache.get((f1, f2))
if result and (s1, s2)==result[:2]:
return result[2]
outcome = _do_cmp(f1, f2)
_cache[f1, f2] = s1, s2, outcome
return outcome
result = _cache.get((f1, f2))
if result and (s1, s2)==result[:2]:
return result[2]
outcome = _do_cmp(f1, f2)
_cache[f1, f2] = s1, s2, outcome
return outcome
def _sig(st):
return (stat.S_IFMT(st[stat.ST_MODE]),
st[stat.ST_SIZE],
st[stat.ST_MTIME])
return (stat.S_IFMT(st[stat.ST_MODE]),
st[stat.ST_SIZE],
st[stat.ST_MTIME])
def _do_cmp(f1, f2):
bufsize = BUFSIZE
fp1 , fp2 = open(f1, 'rb'), open(f2, 'rb')
while 1:
b1, b2 = fp1.read(bufsize), fp2.read(bufsize)
if b1!=b2: return 0
if not b1: return 1
# Directory comparison class.
#
class dircmp:
"""A class that manages the comparison of 2 directories.
dircmp(a,b,ignore=None,hide=None)
A and B are directories.
IGNORE is a list of names to ignore,
defaults to ['RCS', 'CVS', 'tags'].
HIDE is a list of names to hide,
defaults to [os.curdir, os.pardir].
High level usage:
x = dircmp(dir1, dir2)
x.report() -> prints a report on the differences between dir1 and dir2
or
x.report_partial_closure() -> prints report on differences between dir1
and dir2, and reports on common immediate subdirectories.
x.report_full_closure() -> like report_partial_closure,
but fully recursive.
Attributes:
left_list, right_list: The files in dir1 and dir2,
filtered by hide and ignore.
common: a list of names in both dir1 and dir2.
left_only, right_only: names only in dir1, dir2.
common_dirs: subdirectories in both dir1 and dir2.
common_files: files in both dir1 and dir2.
common_funny: names in both dir1 and dir2 where the type differs between
dir1 and dir2, or the name is not stat-able.
same_files: list of identical files.
diff_files: list of filenames which differ.
funny_files: list of files which could not be compared.
subdirs: a dictionary of dircmp objects, keyed by names in common_dirs.
"""
def __init__(self, a, b, ignore=None, hide=None): # Initialize
self.left = a
self.right = b
if hide is None:
self.hide = [os.curdir, os.pardir] # Names never to be shown
else:
self.hide = hide
if ignore is None:
self.ignore = ['RCS', 'CVS', 'tags'] # Names ignored in comparison
else:
self.ignore = ignore
def phase0(self): # Compare everything except common subdirectories
self.left_list = _filter(os.listdir(self.left),
self.hide+self.ignore)
self.right_list = _filter(os.listdir(self.right),
self.hide+self.ignore)
self.left_list.sort()
self.right_list.sort()
__p4_attrs = ('subdirs',)
__p3_attrs = ('same_files', 'diff_files', 'funny_files')
__p2_attrs = ('common_dirs', 'common_files', 'common_funny')
__p1_attrs = ('common', 'left_only', 'right_only')
__p0_attrs = ('left_list', 'right_list')
def __getattr__(self, attr):
if attr in self.__p4_attrs:
self.phase4()
elif attr in self.__p3_attrs:
self.phase3()
elif attr in self.__p2_attrs:
self.phase2()
elif attr in self.__p1_attrs:
self.phase1()
elif attr in self.__p0_attrs:
self.phase0()
else:
raise AttributeError, attr
return getattr(self, attr)
def phase1(self): # Compute common names
a_only, b_only = [], []
common = {}
b = {}
for fnm in self.right_list:
b[fnm] = 1
for x in self.left_list:
if b.get(x, 0):
common[x] = 1
else:
a_only.append(x)
for x in self.right_list:
if common.get(x, 0):
pass
else:
b_only.append(x)
self.common = common.keys()
self.left_only = a_only
self.right_only = b_only
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.left, x)
b_path = os.path.join(self.right, 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 = stat.S_IFMT(a_stat[stat.ST_MODE])
b_type = stat.S_IFMT(b_stat[stat.ST_MODE])
if a_type <> b_type:
self.common_funny.append(x)
elif stat.S_ISDIR(a_type):
self.common_dirs.append(x)
elif stat.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.left, self.right, 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.left, x)
b_x = os.path.join(self.right, x)
self.subdirs[x] = dircmp(a_x, b_x, self.ignore, self.hide)
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
# Output format is purposely lousy
print 'diff', self.left, self.right
if self.left_only:
self.left_only.sort()
print 'Only in', self.left, ':', self.left_only
if self.right_only:
self.right_only.sort()
print 'Only in', self.right, ':', self.right_only
if self.same_files:
self.same_files.sort()
print 'Identical files :', self.same_files
if self.diff_files:
self.diff_files.sort()
print 'Differing files :', self.diff_files
if self.funny_files:
self.funny_files.sort()
print 'Trouble with common files :', self.funny_files
if self.common_dirs:
self.common_dirs.sort()
print 'Common subdirectories :', self.common_dirs
if self.common_funny:
self.common_funny.sort()
print 'Common funny cases :', self.common_funny
def report_partial_closure(self): # Print reports on self and on subdirs
self.report()
for x in self.subdirs.keys():
print
self.subdirs[x].report()
def report_full_closure(self): # Report on self and subdirs recursively
self.report()
for x in self.subdirs.keys():
print
self.subdirs[x].report_full_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):
"""Compare common files in two directories.
cmpfiles(a,b,common)
A and B are directory names
COMMON is a list of file names
returns a tuple of three lists:
files that compare equal
files that are different
filenames that aren't regular files."""
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:
return not abs(cmp(a, b))
except os.error:
return 2
# 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
# 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(args[0], args[1])
if ('-r', '') in options:
dd.report_full_closure()
else:
dd.report()
if __name__ == '__main__':
demo()
bufsize = BUFSIZE
fp1 , fp2 = open(f1, 'rb'), open(f2, 'rb')
while 1:
b1, b2 = fp1.read(bufsize), fp2.read(bufsize)
if b1!=b2: return 0
if not b1: return 1

View File

@@ -22,120 +22,120 @@ decoder = re.compile(r'^([-+]?)0*(\d*)((?:\.\d*)?)(([eE][-+]?\d+)?)$')
# \4 exponent part (empty or begins with 'e' or 'E')
try:
class NotANumber(ValueError):
pass
class NotANumber(ValueError):
pass
except TypeError:
NotANumber = 'fpformat.NotANumber'
NotANumber = 'fpformat.NotANumber'
# Return (sign, intpart, fraction, expo) or raise an exception:
# sign is '+' or '-'
# intpart is 0 or more digits beginning with a nonzero
# fraction is 0 or more digits
# expo is an integer
def extract(s):
res = decoder.match(s)
if res is None: raise NotANumber, s
sign, intpart, fraction, exppart = res.group(1,2,3,4)
if sign == '+': sign = ''
if fraction: fraction = fraction[1:]
if exppart: expo = int(exppart[1:])
else: expo = 0
return sign, intpart, fraction, expo
"""Return (sign, intpart, fraction, expo) or raise an exception:
sign is '+' or '-'
intpart is 0 or more digits beginning with a nonzero
fraction is 0 or more digits
expo is an integer"""
res = decoder.match(s)
if res is None: raise NotANumber, s
sign, intpart, fraction, exppart = res.group(1,2,3,4)
if sign == '+': sign = ''
if fraction: fraction = fraction[1:]
if exppart: expo = int(exppart[1:])
else: expo = 0
return sign, intpart, fraction, expo
# Remove the exponent by changing intpart and fraction
def unexpo(intpart, fraction, expo):
if expo > 0: # Move the point left
f = len(fraction)
intpart, fraction = intpart + fraction[:expo], fraction[expo:]
if expo > f:
intpart = intpart + '0'*(expo-f)
elif expo < 0: # Move the point right
i = len(intpart)
intpart, fraction = intpart[:expo], intpart[expo:] + fraction
if expo < -i:
fraction = '0'*(-expo-i) + fraction
return intpart, fraction
"""Remove the exponent by changing intpart and fraction."""
if expo > 0: # Move the point left
f = len(fraction)
intpart, fraction = intpart + fraction[:expo], fraction[expo:]
if expo > f:
intpart = intpart + '0'*(expo-f)
elif expo < 0: # Move the point right
i = len(intpart)
intpart, fraction = intpart[:expo], intpart[expo:] + fraction
if expo < -i:
fraction = '0'*(-expo-i) + fraction
return intpart, fraction
# Round or extend the fraction to size digs
def roundfrac(intpart, fraction, digs):
f = len(fraction)
if f <= digs:
return intpart, fraction + '0'*(digs-f)
i = len(intpart)
if i+digs < 0:
return '0'*-digs, ''
total = intpart + fraction
nextdigit = total[i+digs]
if nextdigit >= '5': # Hard case: increment last digit, may have carry!
n = i + digs - 1
while n >= 0:
if total[n] != '9': break
n = n-1
else:
total = '0' + total
i = i+1
n = 0
total = total[:n] + chr(ord(total[n]) + 1) + '0'*(len(total)-n-1)
intpart, fraction = total[:i], total[i:]
if digs >= 0:
return intpart, fraction[:digs]
else:
return intpart[:digs] + '0'*-digs, ''
"""Round or extend the fraction to size digs."""
f = len(fraction)
if f <= digs:
return intpart, fraction + '0'*(digs-f)
i = len(intpart)
if i+digs < 0:
return '0'*-digs, ''
total = intpart + fraction
nextdigit = total[i+digs]
if nextdigit >= '5': # Hard case: increment last digit, may have carry!
n = i + digs - 1
while n >= 0:
if total[n] != '9': break
n = n-1
else:
total = '0' + total
i = i+1
n = 0
total = total[:n] + chr(ord(total[n]) + 1) + '0'*(len(total)-n-1)
intpart, fraction = total[:i], total[i:]
if digs >= 0:
return intpart, fraction[:digs]
else:
return intpart[:digs] + '0'*-digs, ''
# Format x as [-]ddd.ddd with 'digs' digits after the point
# and at least one digit before.
# If digs <= 0, the point is suppressed.
def fix(x, digs):
if type(x) != type(''): x = `x`
try:
sign, intpart, fraction, expo = extract(x)
except NotANumber:
return x
intpart, fraction = unexpo(intpart, fraction, expo)
intpart, fraction = roundfrac(intpart, fraction, digs)
while intpart and intpart[0] == '0': intpart = intpart[1:]
if intpart == '': intpart = '0'
if digs > 0: return sign + intpart + '.' + fraction
else: return sign + intpart
"""Format x as [-]ddd.ddd with 'digs' digits after the point
and at least one digit before.
If digs <= 0, the point is suppressed."""
if type(x) != type(''): x = `x`
try:
sign, intpart, fraction, expo = extract(x)
except NotANumber:
return x
intpart, fraction = unexpo(intpart, fraction, expo)
intpart, fraction = roundfrac(intpart, fraction, digs)
while intpart and intpart[0] == '0': intpart = intpart[1:]
if intpart == '': intpart = '0'
if digs > 0: return sign + intpart + '.' + fraction
else: return sign + intpart
# Format x as [-]d.dddE[+-]ddd with 'digs' digits after the point
# and exactly one digit before.
# If digs is <= 0, one digit is kept and the point is suppressed.
def sci(x, digs):
if type(x) != type(''): x = `x`
sign, intpart, fraction, expo = extract(x)
if not intpart:
while fraction and fraction[0] == '0':
fraction = fraction[1:]
expo = expo - 1
if fraction:
intpart, fraction = fraction[0], fraction[1:]
expo = expo - 1
else:
intpart = '0'
else:
expo = expo + len(intpart) - 1
intpart, fraction = intpart[0], intpart[1:] + fraction
digs = max(0, digs)
intpart, fraction = roundfrac(intpart, fraction, digs)
if len(intpart) > 1:
intpart, fraction, expo = \
intpart[0], intpart[1:] + fraction[:-1], \
expo + len(intpart) - 1
s = sign + intpart
if digs > 0: s = s + '.' + fraction
e = `abs(expo)`
e = '0'*(3-len(e)) + e
if expo < 0: e = '-' + e
else: e = '+' + e
return s + 'e' + e
"""Format x as [-]d.dddE[+-]ddd with 'digs' digits after the point
and exactly one digit before.
If digs is <= 0, one digit is kept and the point is suppressed."""
if type(x) != type(''): x = `x`
sign, intpart, fraction, expo = extract(x)
if not intpart:
while fraction and fraction[0] == '0':
fraction = fraction[1:]
expo = expo - 1
if fraction:
intpart, fraction = fraction[0], fraction[1:]
expo = expo - 1
else:
intpart = '0'
else:
expo = expo + len(intpart) - 1
intpart, fraction = intpart[0], intpart[1:] + fraction
digs = max(0, digs)
intpart, fraction = roundfrac(intpart, fraction, digs)
if len(intpart) > 1:
intpart, fraction, expo = \
intpart[0], intpart[1:] + fraction[:-1], \
expo + len(intpart) - 1
s = sign + intpart
if digs > 0: s = s + '.' + fraction
e = `abs(expo)`
e = '0'*(3-len(e)) + e
if expo < 0: e = '-' + e
else: e = '+' + e
return s + 'e' + e
# Interactive test run
def test():
try:
while 1:
x, digs = input('Enter (x, digs): ')
print x, fix(x, digs), sci(x, digs)
except (EOFError, KeyboardInterrupt):
pass
"""Interactive test run."""
try:
while 1:
x, digs = input('Enter (x, digs): ')
print x, fix(x, digs), sci(x, digs)
except (EOFError, KeyboardInterrupt):
pass

View File

@@ -1,4 +1,4 @@
# Gopher protocol client interface
"""Gopher protocol client interface."""
import string
@@ -29,180 +29,180 @@ A_IMAGE = 'I'
A_WHOIS = 'w'
A_QUERY = 'q'
A_GIF = 'g'
A_HTML = 'h' # HTML file
A_WWW = 'w' # WWW address
A_HTML = 'h' # HTML file
A_WWW = 'w' # WWW address
A_PLUS_IMAGE = ':'
A_PLUS_MOVIE = ';'
A_PLUS_SOUND = '<'
# Function mapping all file types to strings; unknown types become TYPE='x'
_names = dir()
_type_to_name_map = {}
def type_to_name(gtype):
global _type_to_name_map
if _type_to_name_map=={}:
for name in _names:
if name[:2] == 'A_':
_type_to_name_map[eval(name)] = name[2:]
if _type_to_name_map.has_key(gtype):
return _type_to_name_map[gtype]
return 'TYPE=' + `gtype`
"""Map all file types to strings; unknown types become TYPE='x'."""
global _type_to_name_map
if _type_to_name_map=={}:
for name in _names:
if name[:2] == 'A_':
_type_to_name_map[eval(name)] = name[2:]
if _type_to_name_map.has_key(gtype):
return _type_to_name_map[gtype]
return 'TYPE=' + `gtype`
# Names for characters and strings
CRLF = '\r\n'
TAB = '\t'
# Send a selector to a given host and port, return a file with the reply
def send_selector(selector, host, port = 0):
import socket
import string
if not port:
i = string.find(host, ':')
if i >= 0:
host, port = host[:i], string.atoi(host[i+1:])
if not port:
port = DEF_PORT
elif type(port) == type(''):
port = string.atoi(port)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(host, port)
s.send(selector + CRLF)
s.shutdown(1)
return s.makefile('rb')
"""Send a selector to a given host and port, return a file with the reply."""
import socket
import string
if not port:
i = string.find(host, ':')
if i >= 0:
host, port = host[:i], string.atoi(host[i+1:])
if not port:
port = DEF_PORT
elif type(port) == type(''):
port = string.atoi(port)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(host, port)
s.send(selector + CRLF)
s.shutdown(1)
return s.makefile('rb')
# Send a selector and a query string
def send_query(selector, query, host, port = 0):
return send_selector(selector + '\t' + query, host, port)
"""Send a selector and a query string."""
return send_selector(selector + '\t' + query, host, port)
# Takes a path as returned by urlparse and returns the appropriate selector
def path_to_selector(path):
if path=="/":
return "/"
else:
return path[2:] # Cuts initial slash and data type identifier
"""Takes a path as returned by urlparse and returns the appropriate selector."""
if path=="/":
return "/"
else:
return path[2:] # Cuts initial slash and data type identifier
# Takes a path as returned by urlparse and maps it to a string
# See section 3.4 of RFC 1738 for details
def path_to_datatype_name(path):
if path=="/":
# No way to tell, although "INDEX" is likely
return "TYPE='unknown'"
else:
return type_to_name(path[1])
"""Takes a path as returned by urlparse and maps it to a string.
See section 3.4 of RFC 1738 for details."""
if path=="/":
# No way to tell, although "INDEX" is likely
return "TYPE='unknown'"
else:
return type_to_name(path[1])
# The following functions interpret the data returned by the gopher
# server according to the expected type, e.g. textfile or directory
# Get a directory in the form of a list of entries
def get_directory(f):
import string
list = []
while 1:
line = f.readline()
if not line:
print '(Unexpected EOF from server)'
break
if line[-2:] == CRLF:
line = line[:-2]
elif line[-1:] in CRLF:
line = line[:-1]
if line == '.':
break
if not line:
print '(Empty line from server)'
continue
gtype = line[0]
parts = string.splitfields(line[1:], TAB)
if len(parts) < 4:
print '(Bad line from server:', `line`, ')'
continue
if len(parts) > 4:
if parts[4:] != ['+']:
print '(Extra info from server:',
print parts[4:], ')'
else:
parts.append('')
parts.insert(0, gtype)
list.append(parts)
return list
"""Get a directory in the form of a list of entries."""
import string
list = []
while 1:
line = f.readline()
if not line:
print '(Unexpected EOF from server)'
break
if line[-2:] == CRLF:
line = line[:-2]
elif line[-1:] in CRLF:
line = line[:-1]
if line == '.':
break
if not line:
print '(Empty line from server)'
continue
gtype = line[0]
parts = string.splitfields(line[1:], TAB)
if len(parts) < 4:
print '(Bad line from server:', `line`, ')'
continue
if len(parts) > 4:
if parts[4:] != ['+']:
print '(Extra info from server:',
print parts[4:], ')'
else:
parts.append('')
parts.insert(0, gtype)
list.append(parts)
return list
# Get a text file as a list of lines, with trailing CRLF stripped
def get_textfile(f):
list = []
get_alt_textfile(f, list.append)
return list
"""Get a text file as a list of lines, with trailing CRLF stripped."""
list = []
get_alt_textfile(f, list.append)
return list
# Get a text file and pass each line to a function, with trailing CRLF stripped
def get_alt_textfile(f, func):
while 1:
line = f.readline()
if not line:
print '(Unexpected EOF from server)'
break
if line[-2:] == CRLF:
line = line[:-2]
elif line[-1:] in CRLF:
line = line[:-1]
if line == '.':
break
if line[:2] == '..':
line = line[1:]
func(line)
"""Get a text file and pass each line to a function, with trailing CRLF stripped."""
while 1:
line = f.readline()
if not line:
print '(Unexpected EOF from server)'
break
if line[-2:] == CRLF:
line = line[:-2]
elif line[-1:] in CRLF:
line = line[:-1]
if line == '.':
break
if line[:2] == '..':
line = line[1:]
func(line)
# Get a binary file as one solid data block
def get_binary(f):
data = f.read()
return data
"""Get a binary file as one solid data block."""
data = f.read()
return data
# Get a binary file and pass each block to a function
def get_alt_binary(f, func, blocksize):
while 1:
data = f.read(blocksize)
if not data:
break
func(data)
"""Get a binary file and pass each block to a function."""
while 1:
data = f.read(blocksize)
if not data:
break
func(data)
# Trivial test program
def test():
import sys
import getopt
opts, args = getopt.getopt(sys.argv[1:], '')
selector = DEF_SELECTOR
type = selector[0]
host = DEF_HOST
port = DEF_PORT
if args:
host = args[0]
args = args[1:]
if args:
type = args[0]
args = args[1:]
if len(type) > 1:
type, selector = type[0], type
else:
selector = ''
if args:
selector = args[0]
args = args[1:]
query = ''
if args:
query = args[0]
args = args[1:]
if type == A_INDEX:
f = send_query(selector, query, host)
else:
f = send_selector(selector, host)
if type == A_TEXT:
list = get_textfile(f)
for item in list: print item
elif type in (A_MENU, A_INDEX):
list = get_directory(f)
for item in list: print item
else:
data = get_binary(f)
print 'binary data:', len(data), 'bytes:', `data[:100]`[:40]
"""Trivial test program."""
import sys
import getopt
opts, args = getopt.getopt(sys.argv[1:], '')
selector = DEF_SELECTOR
type = selector[0]
host = DEF_HOST
port = DEF_PORT
if args:
host = args[0]
args = args[1:]
if args:
type = args[0]
args = args[1:]
if len(type) > 1:
type, selector = type[0], type
else:
selector = ''
if args:
selector = args[0]
args = args[1:]
query = ''
if args:
query = args[0]
args = args[1:]
if type == A_INDEX:
f = send_query(selector, query, host)
else:
f = send_selector(selector, host)
if type == A_TEXT:
list = get_textfile(f)
for item in list: print item
elif type in (A_MENU, A_INDEX):
list = get_directory(f)
for item in list: print item
else:
data = get_binary(f)
print 'binary data:', len(data), 'bytes:', `data[:100]`[:40]
# Run the test when run as script
if __name__ == '__main__':
test()
test()

View File

@@ -1,15 +1,15 @@
"""This module implements a function that reads and writes a gzipped file.
The user of the file doesn't have to worry about the compression,
but random access is not allowed."""
# based on Andrew Kuchling's minigzip.py distributed with the zlib module
import time
import string
import zlib
import struct
import __builtin__
# implements a python function that reads and writes a gzipped file
# the user of the file doesn't have to worry about the compression,
# but random access is not allowed
# based on Andrew Kuchling's minigzip.py distributed with the zlib module
FTEXT, FHCRC, FEXTRA, FNAME, FCOMMENT = 1, 2, 4, 8, 16
READ, WRITE = 1, 2

View File

@@ -1,3 +1,5 @@
"""HTML character entity references."""
entitydefs = {
'AElig': '\306', # latin capital letter AE = latin capital ligature AE, U+00C6 ISOlat1
'Aacute': '\301', # latin capital letter A with acute, U+00C1 ISOlat1

View File

@@ -1,4 +1,4 @@
# Recognizing image files based on their first few bytes.
"""Recognize image file formats based on their first few bytes."""
#-------------------------#
@@ -6,25 +6,25 @@
#-------------------------#
def what(file, h=None):
if h is None:
if type(file) == type(''):
f = open(file, 'rb')
h = f.read(32)
else:
location = file.tell()
h = file.read(32)
file.seek(location)
f = None
else:
f = None
try:
for tf in tests:
res = tf(h, f)
if res:
return res
finally:
if f: f.close()
return None
if h is None:
if type(file) == type(''):
f = open(file, 'rb')
h = f.read(32)
else:
location = file.tell()
h = file.read(32)
file.seek(location)
f = None
else:
f = None
try:
for tf in tests:
res = tf(h, f)
if res:
return res
finally:
if f: f.close()
return None
#---------------------------------#
@@ -34,81 +34,81 @@ def what(file, h=None):
tests = []
def test_rgb(h, f):
# SGI image library
if h[:2] == '\001\332':
return 'rgb'
"""SGI image library"""
if h[:2] == '\001\332':
return 'rgb'
tests.append(test_rgb)
def test_gif(h, f):
# GIF ('87 and '89 variants)
if h[:6] in ('GIF87a', 'GIF89a'):
return 'gif'
"""GIF ('87 and '89 variants)"""
if h[:6] in ('GIF87a', 'GIF89a'):
return 'gif'
tests.append(test_gif)
def test_pbm(h, f):
# PBM (portable bitmap)
if len(h) >= 3 and \
h[0] == 'P' and h[1] in '14' and h[2] in ' \t\n\r':
return 'pbm'
"""PBM (portable bitmap)"""
if len(h) >= 3 and \
h[0] == 'P' and h[1] in '14' and h[2] in ' \t\n\r':
return 'pbm'
tests.append(test_pbm)
def test_pgm(h, f):
# PGM (portable graymap)
if len(h) >= 3 and \
h[0] == 'P' and h[1] in '25' and h[2] in ' \t\n\r':
return 'pgm'
"""PGM (portable graymap)"""
if len(h) >= 3 and \
h[0] == 'P' and h[1] in '25' and h[2] in ' \t\n\r':
return 'pgm'
tests.append(test_pgm)
def test_ppm(h, f):
# PPM (portable pixmap)
if len(h) >= 3 and \
h[0] == 'P' and h[1] in '36' and h[2] in ' \t\n\r':
return 'ppm'
"""PPM (portable pixmap)"""
if len(h) >= 3 and \
h[0] == 'P' and h[1] in '36' and h[2] in ' \t\n\r':
return 'ppm'
tests.append(test_ppm)
def test_tiff(h, f):
# TIFF (can be in Motorola or Intel byte order)
if h[:2] in ('MM', 'II'):
return 'tiff'
"""TIFF (can be in Motorola or Intel byte order)"""
if h[:2] in ('MM', 'II'):
return 'tiff'
tests.append(test_tiff)
def test_rast(h, f):
# Sun raster file
if h[:4] == '\x59\xA6\x6A\x95':
return 'rast'
"""Sun raster file"""
if h[:4] == '\x59\xA6\x6A\x95':
return 'rast'
tests.append(test_rast)
def test_xbm(h, f):
# X bitmap (X10 or X11)
s = '#define '
if h[:len(s)] == s:
return 'xbm'
"""X bitmap (X10 or X11)"""
s = '#define '
if h[:len(s)] == s:
return 'xbm'
tests.append(test_xbm)
def test_jpeg(h, f):
# JPEG data in JFIF format
if h[6:10] == 'JFIF':
return 'jpeg'
"""JPEG data in JFIF format"""
if h[6:10] == 'JFIF':
return 'jpeg'
tests.append(test_jpeg)
def test_bmp(h, f):
if h[:2] == 'BM':
return 'bmp'
if h[:2] == 'BM':
return 'bmp'
tests.append(test_bmp)
def test_png(h, f):
if h[:8] == "\211PNG\r\n\032\n":
return 'png'
if h[:8] == "\211PNG\r\n\032\n":
return 'png'
tests.append(test_png)
@@ -117,37 +117,37 @@ tests.append(test_png)
#--------------------#
def test():
import sys
recursive = 0
if sys.argv[1:] and sys.argv[1] == '-r':
del sys.argv[1:2]
recursive = 1
try:
if sys.argv[1:]:
testall(sys.argv[1:], recursive, 1)
else:
testall(['.'], recursive, 1)
except KeyboardInterrupt:
sys.stderr.write('\n[Interrupted]\n')
sys.exit(1)
import sys
recursive = 0
if sys.argv[1:] and sys.argv[1] == '-r':
del sys.argv[1:2]
recursive = 1
try:
if sys.argv[1:]:
testall(sys.argv[1:], recursive, 1)
else:
testall(['.'], recursive, 1)
except KeyboardInterrupt:
sys.stderr.write('\n[Interrupted]\n')
sys.exit(1)
def testall(list, recursive, toplevel):
import sys
import os
for filename in list:
if os.path.isdir(filename):
print filename + '/:',
if recursive or toplevel:
print 'recursing down:'
import glob
names = glob.glob(os.path.join(filename, '*'))
testall(names, recursive, 0)
else:
print '*** directory (use -r) ***'
else:
print filename + ':',
sys.stdout.flush()
try:
print what(filename)
except IOError:
print '*** not found ***'
import sys
import os
for filename in list:
if os.path.isdir(filename):
print filename + '/:',
if recursive or toplevel:
print 'recursing down:'
import glob
names = glob.glob(os.path.join(filename, '*'))
testall(names, recursive, 0)
else:
print '*** directory (use -r) ***'
else:
print filename + ':',
sys.stdout.flush()
try:
print what(filename)
except IOError:
print '*** not found ***'

View File

@@ -1,13 +1,14 @@
#! /usr/bin/env python
#
# Keywords (from "graminit.c")
#
# This file is automatically generated; please don't muck it up!
#
# To update the symbols in this file, 'cd' to the top directory of
# the python source tree after building the interpreter and run:
#
# python Lib/keyword.py
"""Keywords (from "graminit.c")
This file is automatically generated; please don't muck it up!
To update the symbols in this file, 'cd' to the top directory of
the python source tree after building the interpreter and run:
python Lib/keyword.py
"""
kwlist = [
#--start keywords--

View File

@@ -1,18 +1,20 @@
# Cache lines from files.
# This is intended to read lines from modules imported -- hence if a filename
# is not found, it will look down the module search path for a file by
# that name.
"""Cache lines from files.
This is intended to read lines from modules imported -- hence if a filename
is not found, it will look down the module search path for a file by
that name.
"""
import sys
import os
from stat import *
def getline(filename, lineno):
lines = getlines(filename)
if 1 <= lineno <= len(lines):
return lines[lineno-1]
else:
return ''
lines = getlines(filename)
if 1 <= lineno <= len(lines):
return lines[lineno-1]
else:
return ''
# The cache
@@ -20,71 +22,71 @@ def getline(filename, lineno):
cache = {} # The cache
# Clear the cache entirely
def clearcache():
global cache
cache = {}
"""Clear the cache entirely."""
global cache
cache = {}
# Get the lines for a file from the cache.
# Update the cache if it doesn't contain an entry for this file already.
def getlines(filename):
if cache.has_key(filename):
return cache[filename][2]
else:
return updatecache(filename)
"""Get the lines for a file from the cache.
Update the cache if it doesn't contain an entry for this file already."""
if cache.has_key(filename):
return cache[filename][2]
else:
return updatecache(filename)
# Discard cache entries that are out of date.
# (This is not checked upon each call!)
def checkcache():
for filename in cache.keys():
size, mtime, lines, fullname = cache[filename]
try:
stat = os.stat(fullname)
except os.error:
del cache[filename]
continue
if size <> stat[ST_SIZE] or mtime <> stat[ST_MTIME]:
del cache[filename]
"""Discard cache entries that are out of date.
(This is not checked upon each call!)"""
for filename in cache.keys():
size, mtime, lines, fullname = cache[filename]
try:
stat = os.stat(fullname)
except os.error:
del cache[filename]
continue
if size <> stat[ST_SIZE] or mtime <> stat[ST_MTIME]:
del cache[filename]
# Update a cache entry and return its list of lines.
# If something's wrong, print a message, discard the cache entry,
# and return an empty list.
def updatecache(filename):
if cache.has_key(filename):
del cache[filename]
if not filename or filename[0] + filename[-1] == '<>':
return []
fullname = filename
try:
stat = os.stat(fullname)
except os.error, msg:
# Try looking through the module search path
basename = os.path.split(filename)[1]
for dirname in sys.path:
fullname = os.path.join(dirname, basename)
try:
stat = os.stat(fullname)
break
except os.error:
pass
else:
# No luck
## print '*** Cannot stat', filename, ':', msg
return []
try:
fp = open(fullname, 'r')
lines = fp.readlines()
fp.close()
except IOError, msg:
## print '*** Cannot open', fullname, ':', msg
return []
size, mtime = stat[ST_SIZE], stat[ST_MTIME]
cache[filename] = size, mtime, lines, fullname
return lines
"""Update a cache entry and return its list of lines.
If something's wrong, print a message, discard the cache entry,
and return an empty list."""
if cache.has_key(filename):
del cache[filename]
if not filename or filename[0] + filename[-1] == '<>':
return []
fullname = filename
try:
stat = os.stat(fullname)
except os.error, msg:
# Try looking through the module search path
basename = os.path.split(filename)[1]
for dirname in sys.path:
fullname = os.path.join(dirname, basename)
try:
stat = os.stat(fullname)
break
except os.error:
pass
else:
# No luck
## print '*** Cannot stat', filename, ':', msg
return []
try:
fp = open(fullname, 'r')
lines = fp.readlines()
fp.close()
except IOError, msg:
## print '*** Cannot open', fullname, ':', msg
return []
size, mtime = stat[ST_SIZE], stat[ST_MTIME]
cache[filename] = size, mtime, lines, fullname
return lines

View File

@@ -1,4 +1,4 @@
# module 'macpath' -- pathname (or -related) operations for the Macintosh
"""Pathname and path-related operations for the Macintosh."""
import string
import os
@@ -10,77 +10,77 @@ from stat import *
normcase = string.lower
# Return true if a path is absolute.
# On the Mac, relative paths begin with a colon,
# but as a special case, paths with no colons at all are also relative.
# Anything else is absolute (the string up to the first colon is the
# volume name).
def isabs(s):
return ':' in s and s[0] <> ':'
"""Return true if a path is absolute.
On the Mac, relative paths begin with a colon,
but as a special case, paths with no colons at all are also relative.
Anything else is absolute (the string up to the first colon is the
volume name)."""
return ':' in s and s[0] <> ':'
def join(s, *p):
path = s
for t in p:
if (not s) or isabs(t):
path = t
continue
if t[:1] == ':':
t = t[1:]
if ':' not in path:
path = ':' + path
if path[-1:] <> ':':
path = path + ':'
path = path + t
return path
path = s
for t in p:
if (not s) or isabs(t):
path = t
continue
if t[:1] == ':':
t = t[1:]
if ':' not in path:
path = ':' + path
if path[-1:] <> ':':
path = path + ':'
path = path + t
return path
# Split a pathname in two parts: the directory leading up to the final bit,
# and the basename (the filename, without colons, in that directory).
# The result (s, t) is such that join(s, t) yields the original argument.
def split(s):
if ':' not in s: return '', s
colon = 0
for i in range(len(s)):
if s[i] == ':': colon = i+1
path, file = s[:colon-1], s[colon:]
if path and not ':' in path:
path = path + ':'
return path, file
"""Split a pathname into two parts: the directory leading up to the final
bit, and the basename (the filename, without colons, in that directory).
The result (s, t) is such that join(s, t) yields the original argument."""
if ':' not in s: return '', s
colon = 0
for i in range(len(s)):
if s[i] == ':': colon = i+1
path, file = s[:colon-1], s[colon:]
if path and not ':' in path:
path = path + ':'
return path, file
# Split a path in root and extension.
# The extension is everything starting at the last dot in the last
# pathname component; the root is everything before that.
# It is always true that root + ext == p.
def splitext(p):
root, ext = '', ''
for c in p:
if c == ':':
root, ext = root + ext + c, ''
elif c == '.':
if ext:
root, ext = root + ext, c
else:
ext = c
elif ext:
ext = ext + c
else:
root = root + c
return root, ext
"""Split a path into root and extension.
The extension is everything starting at the last dot in the last
pathname component; the root is everything before that.
It is always true that root + ext == p."""
root, ext = '', ''
for c in p:
if c == ':':
root, ext = root + ext + c, ''
elif c == '.':
if ext:
root, ext = root + ext, c
else:
ext = c
elif ext:
ext = ext + c
else:
root = root + c
return root, ext
# Split a pathname into a drive specification and the rest of the
# path. Useful on DOS/Windows/NT; on the Mac, the drive is always
# empty (don't use the volume name -- it doesn't have the same
# syntactic and semantic oddities as DOS drive letters, such as there
# being a separate current directory per drive).
def splitdrive(p):
return '', p
"""Split a pathname into a drive specification and the rest of the
path. Useful on DOS/Windows/NT; on the Mac, the drive is always
empty (don't use the volume name -- it doesn't have the same
syntactic and semantic oddities as DOS drive letters, such as there
being a separate current directory per drive)."""
return '', p
# Short interfaces to split()
@@ -89,14 +89,14 @@ def dirname(s): return split(s)[0]
def basename(s): return split(s)[1]
# Return true if the pathname refers to an existing directory.
def isdir(s):
try:
st = os.stat(s)
except os.error:
return 0
return S_ISDIR(st[ST_MODE])
"""Return true if the pathname refers to an existing directory."""
try:
st = os.stat(s)
except os.error:
return 0
return S_ISDIR(st[ST_MODE])
# Get size, mtime, atime of files.
@@ -117,105 +117,103 @@ def getatime(filename):
return st[ST_MTIME]
# Return true if the pathname refers to a symbolic link.
# (Always false on the Mac, until we understand Aliases.)
def islink(s):
return 0
"""Return true if the pathname refers to a symbolic link.
Always false on the Mac, until we understand Aliases.)"""
return 0
# Return true if the pathname refers to an existing regular file.
def isfile(s):
try:
st = os.stat(s)
except os.error:
return 0
return S_ISREG(st[ST_MODE])
"""Return true if the pathname refers to an existing regular file."""
try:
st = os.stat(s)
except os.error:
return 0
return S_ISREG(st[ST_MODE])
# Return true if the pathname refers to an existing file or directory.
def exists(s):
try:
st = os.stat(s)
except os.error:
return 0
return 1
"""Return true if the pathname refers to an existing file or directory."""
try:
st = os.stat(s)
except os.error:
return 0
return 1
#
# dummy expandvars to retain interface-compatability with other
# operating systems.
def expandvars(path):
return path
"""Dummy to retain interface-compatibility with other operating systems."""
return path
#
# dummy expanduser to retain interface-compatability with other
# operating systems.
def expanduser(path):
return path
# Normalize a pathname: get rid of '::' sequences by backing up,
# e.g., 'foo:bar::bletch' becomes 'foo:bletch'.
# Raise the exception norm_error below if backing up is impossible,
# e.g., for '::foo'.
# XXX The Unix version doesn't raise an exception but simply
# returns an unnormalized path. Should do so here too.
"""Dummy to retain interface-compatibility with other operating systems."""
return path
norm_error = 'macpath.norm_error: path cannot be normalized'
def normpath(s):
import string
if ':' not in s:
return ':' + s
f = string.splitfields(s, ':')
pre = []
post = []
if not f[0]:
pre = f[:1]
f = f[1:]
if not f[len(f)-1]:
post = f[-1:]
f = f[:-1]
res = []
for seg in f:
if seg:
res.append(seg)
else:
if not res: raise norm_error, 'path starts with ::'
del res[len(res)-1]
if not (pre or res):
raise norm_error, 'path starts with volume::'
if pre: res = pre + res
if post: res = res + post
s = res[0]
for seg in res[1:]:
s = s + ':' + seg
return s
"""Normalize a pathname: get rid of '::' sequences by backing up,
e.g., 'foo:bar::bletch' becomes 'foo:bletch'.
Raise the exception norm_error below if backing up is impossible,
e.g., for '::foo'."""
# XXX The Unix version doesn't raise an exception but simply
# returns an unnormalized path. Should do so here too.
import string
if ':' not in s:
return ':' + s
f = string.splitfields(s, ':')
pre = []
post = []
if not f[0]:
pre = f[:1]
f = f[1:]
if not f[len(f)-1]:
post = f[-1:]
f = f[:-1]
res = []
for seg in f:
if seg:
res.append(seg)
else:
if not res: raise norm_error, 'path starts with ::'
del res[len(res)-1]
if not (pre or res):
raise norm_error, 'path starts with volume::'
if pre: res = pre + res
if post: res = res + post
s = res[0]
for seg in res[1:]:
s = s + ':' + seg
return s
# Directory tree walk.
# For each directory under top (including top itself),
# func(arg, dirname, filenames) is called, where
# dirname is the name of the directory and filenames is the list
# of files (and subdirectories etc.) in the directory.
# The func may modify the filenames list, to implement a filter,
# or to impose a different order of visiting.
def walk(top, func, arg):
try:
names = os.listdir(top)
except os.error:
return
func(arg, top, names)
for name in names:
name = join(top, name)
if isdir(name):
walk(name, func, arg)
"""Directory tree walk.
For each directory under top (including top itself),
func(arg, dirname, filenames) is called, where
dirname is the name of the directory and filenames is the list
of files (and subdirectories etc.) in the directory.
The func may modify the filenames list, to implement a filter,
or to impose a different order of visiting."""
try:
names = os.listdir(top)
except os.error:
return
func(arg, top, names)
for name in names:
name = join(top, name)
if isdir(name):
walk(name, func, arg)
# Return an absolute path.
def abspath(path):
"""Return an absolute path."""
if not isabs(path):
path = join(os.getcwd(), path)
return normpath(path)

View File

@@ -9,8 +9,11 @@ import string
def getcaps():
"""Return a dictionary containing the mailcap database.
The dictionary maps a MIME type (in all lowercase,
e.g. 'text/plain') to a list of corresponding mailcap entries.
The dictionary maps a MIME type (in all lowercase, e.g. 'text/plain')
to a list of dictionaries corresponding to mailcap entries. The list
collects all the entries for that MIME type from all available mailcap
files. Each dictionary contains key-value pairs for that MIME type,
where the viewing command is stored with the key "view".
"""
caps = {}
@@ -48,6 +51,14 @@ def listmailcapfiles():
# Part 2: the parser.
def readmailcapfile(fp):
"""Read a mailcap file and return a dictionary keyed by MIME type.
Each MIME type is mapped to an entry consisting of a list of
dictionaries; the list will contain more than one such dictionary
if a given MIME type appears more than once in the mailcap file.
Each dictionary contains key-value pairs for that MIME type, where
the viewing command is stored with the key "view".
"""
caps = {}
while 1:
line = fp.readline()
@@ -78,6 +89,11 @@ def readmailcapfile(fp):
return caps
def parseline(line):
"""Parse one entry in a mailcap file and return a dictionary.
The viewing command is stored as the value with the key "view",
and the rest of the fields produce key-value pairs in the dict.
"""
fields = []
i, n = 0, len(line)
while i < n:
@@ -104,6 +120,7 @@ def parseline(line):
return key, fields
def parsefield(line, i, n):
"""Separate one key-value pair in a mailcap entry."""
start = i
while i < n:
c = line[i]

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
# Various tools used by MIME-reading or MIME-writing programs.
"""Various tools used by MIME-reading or MIME-writing programs."""
import os
@@ -7,10 +7,9 @@ import string
import tempfile
# A derived class of rfc822.Message that knows about MIME headers and
# contains some hooks for decoding encoded and multipart messages.
class Message(rfc822.Message):
"""A derived class of rfc822.Message that knows about MIME headers and
contains some hooks for decoding encoded and multipart messages."""
def __init__(self, fp, seekable = 1):
rfc822.Message.__init__(self, fp, seekable)
@@ -96,17 +95,17 @@ class Message(rfc822.Message):
# -----------------
# Return a random string usable as a multipart boundary.
# The method used is so that it is *very* unlikely that the same
# string of characters will every occur again in the Universe,
# so the caller needn't check the data it is packing for the
# occurrence of the boundary.
#
# The boundary contains dots so you have to quote it in the header.
_prefix = None
def choose_boundary():
"""Return a random string usable as a multipart boundary.
The method used is so that it is *very* unlikely that the same
string of characters will every occur again in the Universe,
so the caller needn't check the data it is packing for the
occurrence of the boundary.
The boundary contains dots so you have to quote it in the header."""
global _prefix
import time
import random
@@ -131,6 +130,7 @@ def choose_boundary():
# Subroutines for decoding some common content-transfer-types
def decode(input, output, encoding):
"""Decode common content-transfer-encodings (base64, quopri, uuencode)."""
if encoding == 'base64':
import base64
return base64.decode(input, output)
@@ -147,6 +147,7 @@ def decode(input, output, encoding):
'unknown Content-Transfer-Encoding: %s' % encoding
def encode(input, output, encoding):
"""Encode common content-transfer-encodings (base64, quopri, uuencode)."""
if encoding == 'base64':
import base64
return base64.encode(input, output)

View File

@@ -2,7 +2,7 @@
'''Mimification and unmimification of mail messages.
decode quoted-printable parts of a mail message or encode using
Decode quoted-printable parts of a mail message or encode using
quoted-printable.
Usage:
@@ -39,9 +39,8 @@ mime_head = re.compile('=\\?iso-8859-1\\?q\\?([^? \t\n]+)\\?=', re.I)
repl = re.compile('^subject:\\s+re: ', re.I)
class File:
'''A simple fake file object that knows about limited
read-ahead and boundaries.
The only supported method is readline().'''
"""A simple fake file object that knows about limited read-ahead and
boundaries. The only supported method is readline()."""
def __init__(self, file, boundary):
self.file = file
@@ -87,7 +86,7 @@ class HeaderFile:
self.peek = None
def mime_decode(line):
'''Decode a single line of quoted-printable text to 8bit.'''
"""Decode a single line of quoted-printable text to 8bit."""
newline = ''
pos = 0
while 1:
@@ -100,7 +99,7 @@ def mime_decode(line):
return newline + line[pos:]
def mime_decode_header(line):
'''Decode a header line to 8bit.'''
"""Decode a header line to 8bit."""
newline = ''
pos = 0
while 1:
@@ -115,7 +114,7 @@ def mime_decode_header(line):
return newline + line[pos:]
def unmimify_part(ifile, ofile, decode_base64 = 0):
'''Convert a quoted-printable part of a MIME mail message to 8bit.'''
"""Convert a quoted-printable part of a MIME mail message to 8bit."""
multipart = None
quoted_printable = 0
is_base64 = 0
@@ -200,7 +199,7 @@ def unmimify_part(ifile, ofile, decode_base64 = 0):
ofile.write(pref + line)
def unmimify(infile, outfile, decode_base64 = 0):
'''Convert quoted-printable parts of a MIME mail message to 8bit.'''
"""Convert quoted-printable parts of a MIME mail message to 8bit."""
if type(infile) == type(''):
ifile = open(infile)
if type(outfile) == type('') and infile == outfile:
@@ -221,8 +220,8 @@ mime_char = re.compile('[=\177-\377]') # quote these chars in body
mime_header_char = re.compile('[=?\177-\377]') # quote these in header
def mime_encode(line, header):
'''Code a single line as quoted-printable.
If header is set, quote some extra characters.'''
"""Code a single line as quoted-printable.
If header is set, quote some extra characters."""
if header:
reg = mime_header_char
else:
@@ -255,7 +254,7 @@ def mime_encode(line, header):
mime_header = re.compile('([ \t(]|^)([-a-zA-Z0-9_+]*[\177-\377][-a-zA-Z0-9_+\177-\377]*)([ \t)]|\n)')
def mime_encode_header(line):
'''Code a single header line as quoted-printable.'''
"""Code a single header line as quoted-printable."""
newline = ''
pos = 0
while 1:
@@ -273,7 +272,7 @@ cte = re.compile('^content-transfer-encoding:', re.I)
iso_char = re.compile('[\177-\377]')
def mimify_part(ifile, ofile, is_mime):
'''Convert an 8bit part of a MIME mail message to quoted-printable.'''
"""Convert an 8bit part of a MIME mail message to quoted-printable."""
has_cte = is_qp = is_base64 = 0
multipart = None
must_quote_body = must_quote_header = has_iso_chars = 0
@@ -408,7 +407,7 @@ def mimify_part(ifile, ofile, is_mime):
ofile.write(line)
def mimify(infile, outfile):
'''Convert 8bit parts of a MIME mail message to quoted-printable.'''
"""Convert 8bit parts of a MIME mail message to quoted-printable."""
if type(infile) == type(''):
ifile = open(infile)
if type(outfile) == type('') and infile == outfile:

View File

@@ -1,28 +1,31 @@
# A class that makes each part of a multipart message "feel" like an
# ordinary file, as long as you use fp.readline(). Allows recursive
# use, for nested multipart messages. Probably best used together
# with module mimetools.
#
# Suggested use:
#
# real_fp = open(...)
# fp = MultiFile(real_fp)
#
# "read some lines from fp"
# fp.push(separator)
# while 1:
# "read lines from fp until it returns an empty string" (A)
# if not fp.next(): break
# fp.pop()
# "read remaining lines from fp until it returns an empty string"
#
# The latter sequence may be used recursively at (A).
# It is also allowed to use multiple push()...pop() sequences.
#
# If seekable is given as 0, the class code will not do the bookeeping
# it normally attempts in order to make seeks relative to the beginning of the
# current file part. This may be useful when using MultiFile with a non-
# seekable stream object.
"""A readline()-style interface to the parts of a multipart message.
The MultiFile class makes each part of a multipart message "feel" like
an ordinary file, as long as you use fp.readline(). Allows recursive
use, for nested multipart messages. Probably best used together
with module mimetools.
Suggested use:
real_fp = open(...)
fp = MultiFile(real_fp)
"read some lines from fp"
fp.push(separator)
while 1:
"read lines from fp until it returns an empty string" (A)
if not fp.next(): break
fp.pop()
"read remaining lines from fp until it returns an empty string"
The latter sequence may be used recursively at (A).
It is also allowed to use multiple push()...pop() sequences.
If seekable is given as 0, the class code will not do the bookeeping
it normally attempts in order to make seeks relative to the beginning of the
current file part. This may be useful when using MultiFile with a non-
seekable stream object.
"""
import sys
import string
@@ -30,9 +33,9 @@ import string
Error = 'multifile.Error'
class MultiFile:
#
seekable = 0
#
def __init__(self, fp, seekable=1):
self.fp = fp
self.stack = [] # Grows down
@@ -42,12 +45,12 @@ class MultiFile:
self.seekable = 1
self.start = self.fp.tell()
self.posstack = [] # Grows down
#
def tell(self):
if self.level > 0:
return self.lastpos
return self.fp.tell() - self.start
#
def seek(self, pos, whence=0):
here = self.tell()
if whence:
@@ -64,7 +67,7 @@ class MultiFile:
self.fp.seek(pos + self.start)
self.level = 0
self.last = 0
#
def readline(self):
if self.level > 0:
return ''
@@ -105,7 +108,7 @@ class MultiFile:
if self.level > 1:
raise Error,'Missing endmarker in MultiFile.readline()'
return ''
#
def readlines(self):
list = []
while 1:
@@ -113,10 +116,10 @@ class MultiFile:
if not line: break
list.append(line)
return list
#
def read(self): # Note: no size argument -- read until EOF only!
return string.joinfields(self.readlines(), '')
#
def next(self):
while self.readline(): pass
if self.level > 1 or self.last:
@@ -126,7 +129,7 @@ class MultiFile:
if self.seekable:
self.start = self.fp.tell()
return 1
#
def push(self, sep):
if self.level > 0:
raise Error, 'bad MultiFile.push() call'
@@ -134,7 +137,7 @@ class MultiFile:
if self.seekable:
self.posstack.insert(0, self.start)
self.start = self.fp.tell()
#
def pop(self):
if self.stack == []:
raise Error, 'bad MultiFile.pop() call'
@@ -149,12 +152,12 @@ class MultiFile:
del self.posstack[0]
if self.level > 0:
self.lastpos = abslastpos - self.start
#
def is_data(self, line):
return line[:2] <> '--'
#
def section_divider(self, str):
return "--" + str
#
def end_marker(self, str):
return "--" + str + "--"

View File

@@ -1,58 +1,51 @@
# Mutual exclusion -- for use with module sched
"""Mutual exclusion -- for use with module sched
A mutex has two pieces of state -- a 'locked' bit and a queue.
When the mutex is not locked, the queue is empty.
Otherwise, the queue contains 0 or more (function, argument) pairs
representing functions (or methods) waiting to acquire the lock.
When the mutex is unlocked while the queue is not empty,
the first queue entry is removed and its function(argument) pair called,
implying it now has the lock.
Of course, no multi-threading is implied -- hence the funny interface
for lock, where a function is called once the lock is aquired.
"""
# A mutex has two pieces of state -- a 'locked' bit and a queue.
# When the mutex is not locked, the queue is empty.
# Otherwise, the queue contains 0 or more (function, argument) pairs
# representing functions (or methods) waiting to acquire the lock.
# When the mutex is unlocked while the queue is not empty,
# the first queue entry is removed and its function(argument) pair called,
# implying it now has the lock.
#
# Of course, no multi-threading is implied -- hence the funny interface
# for lock, where a function is called once the lock is aquired.
#
class mutex:
#
# Create a new mutex -- initially unlocked
#
def __init__(self):
"""Create a new mutex -- initially unlocked."""
self.locked = 0
self.queue = []
#
# Test the locked bit of the mutex
#
def test(self):
"""Test the locked bit of the mutex."""
return self.locked
#
# Atomic test-and-set -- grab the lock if it is not set,
# return true if it succeeded
#
def testandset(self):
"""Atomic test-and-set -- grab the lock if it is not set,
return true if it succeeded."""
if not self.locked:
self.locked = 1
return 1
else:
return 0
#
# Lock a mutex, call the function with supplied argument
# when it is acquired.
# If the mutex is already locked, place function and argument
# in the queue.
#
def lock(self, function, argument):
"""Lock a mutex, call the function with supplied argument
when it is acquired. If the mutex is already locked, place
function and argument in the queue."""
if self.testandset():
function(argument)
else:
self.queue.append((function, argument))
#
# Unlock a mutex. If the queue is not empty, call the next
# function with its argument.
#
def unlock(self):
"""Unlock a mutex. If the queue is not empty, call the next
function with its argument."""
if self.queue:
function, argument = self.queue[0]
del self.queue[0]
function(argument)
else:
self.locked = 0
#

View File

@@ -1,3 +1,5 @@
"""An object-oriented interface to .netrc files."""
# Module and documentation by Eric S. Raymond, 21 Dec 1998
import os, shlex
@@ -63,7 +65,7 @@ class netrc:
raise SyntaxError, "bad follower token %s, file %s, line %d"%(tt,file,lexer.lineno)
def authenticators(self, host):
"Return a (user, account, password) tuple for given host."
"""Return a (user, account, password) tuple for given host."""
if self.hosts.has_key(host):
return self.hosts[host]
elif self.hosts.has_key('default'):
@@ -72,7 +74,7 @@ class netrc:
return None
def __repr__(self):
"Dump the class data in the format of a .netrc file"
"""Dump the class data in the format of a .netrc file."""
rep = ""
for host in self.hosts.keys():
attrs = self.hosts[host]

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,4 @@
#
# nturl2path convert a NT pathname to a file URL and
# vice versa
"""Convert a NT pathname to a file URL and vice versa."""
def url2pathname(url):
""" Convert a URL to a DOS path...
@@ -34,7 +32,6 @@ def url2pathname(url):
return path
def pathname2url(p):
""" Convert a DOS path name to a file url...
C:\foo\bar\spam.foo

View File

@@ -1,21 +1,22 @@
# os.py -- either mac, dos or posix depending on what system we're on.
"""os.py -- either mac, dos or posix depending on what system we're on.
# This exports:
# - all functions from either posix or mac, e.g., os.unlink, os.stat, etc.
# - os.path is either module posixpath or macpath
# - os.name is either 'posix' or 'mac'
# - os.curdir is a string representing the current directory ('.' or ':')
# - os.pardir is a string representing the parent directory ('..' or '::')
# - os.sep is the (or a most common) pathname separator ('/' or ':' or '\\')
# - os.altsep is the alternatte pathname separator (None or '/')
# - os.pathsep is the component separator used in $PATH etc
# - os.defpath is the default search path for executables
This exports:
- all functions from either posix or mac, e.g., os.unlink, os.stat, etc.
- os.path is either module posixpath or macpath
- os.name is either 'posix' or 'mac'
- os.curdir is a string representing the current directory ('.' or ':')
- os.pardir is a string representing the parent directory ('..' or '::')
- os.sep is the (or a most common) pathname separator ('/' or ':' or '\\')
- os.altsep is the alternatte pathname separator (None or '/')
- os.pathsep is the component separator used in $PATH etc
- os.defpath is the default search path for executables
# Programs that import and use 'os' stand a better chance of being
# portable between different platforms. Of course, they must then
# only use functions that are defined by all platforms (e.g., unlink
# and opendir), and leave all pathname manipulation to os.path
# (e.g., split and join).
Programs that import and use 'os' stand a better chance of being
portable between different platforms. Of course, they must then
only use functions that are defined by all platforms (e.g., unlink
and opendir), and leave all pathname manipulation to os.path
(e.g., split and join).
"""
import sys

Some files were not shown because too many files have changed in this diff Show More