mirror of
https://github.com/AdaCore/cpython.git
synced 2026-02-12 12:57:15 -08:00
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:
438
Lib/dospath.py
438
Lib/dospath.py
File diff suppressed because it is too large
Load Diff
337
Lib/filecmp.py
337
Lib/filecmp.py
@@ -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
|
||||
|
||||
206
Lib/fpformat.py
206
Lib/fpformat.py
@@ -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
|
||||
|
||||
|
||||
280
Lib/gopherlib.py
280
Lib/gopherlib.py
@@ -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()
|
||||
|
||||
12
Lib/gzip.py
12
Lib/gzip.py
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
176
Lib/imghdr.py
176
Lib/imghdr.py
@@ -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 ***'
|
||||
|
||||
@@ -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--
|
||||
|
||||
130
Lib/linecache.py
130
Lib/linecache.py
@@ -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
|
||||
|
||||
276
Lib/macpath.py
276
Lib/macpath.py
@@ -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)
|
||||
|
||||
@@ -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]
|
||||
|
||||
297
Lib/mhlib.py
297
Lib/mhlib.py
File diff suppressed because it is too large
Load Diff
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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 + "--"
|
||||
|
||||
59
Lib/mutex.py
59
Lib/mutex.py
@@ -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
|
||||
#
|
||||
|
||||
@@ -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]
|
||||
|
||||
342
Lib/nntplib.py
342
Lib/nntplib.py
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
|
||||
33
Lib/os.py
33
Lib/os.py
@@ -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
Reference in New Issue
Block a user