AppPkg/Applications/Python: Add Python 2.7.2 sources since the release of Python 2.7.3 made them unavailable from the python.org web site.

These files are a subset of the python-2.7.2.tgz distribution from python.org.  Changed files from PyMod-2.7.2 have been copied into the corresponding directories of this tree, replacing the original files in the distribution.

Signed-off-by: daryl.mcdaniel@intel.com


git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13197 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
darylm503
2012-04-16 22:12:42 +00:00
parent cbc6b5e545
commit 4710c53dca
2106 changed files with 871583 additions and 0 deletions

View File

@ -0,0 +1,22 @@
This directory contains a collection of executable Python scripts.
See also the Tools/scripts directory!
beer.py Print the classic 'bottles of beer' list
eqfix.py Fix .py files to use the correct equality test operator
fact.py Factorize numbers
find-uname.py Search for Unicode characters using regexps
from.py Summarize mailbox
lpwatch.py Watch BSD line printer queues
makedir.py Like mkdir -p
markov.py Markov chain simulation of words or characters
mboxconvert.py Convert MH or MMDF mailboxes to unix mailbox format
morse.py Produce morse code (audible or on AIFF file)
newslist.py List all newsgroups on a NNTP server as HTML pages
pi.py Print all digits of pi -- given enough time and memory
pp.py Emulate some Perl command line options
primes.py Print prime numbers
queens.py Dijkstra's solution to Wirth's "N Queens problem"
script.py Equivalent to BSD script(1) -- by Steen Lumholt
unbirthday.py Print unbirthday count
update.py Update a bunch of files according to a script.

View File

@ -0,0 +1,20 @@
#! /usr/bin/env python
# By GvR, demystified after a version by Fredrik Lundh.
import sys
n = 100
if sys.argv[1:]:
n = int(sys.argv[1])
def bottle(n):
if n == 0: return "no more bottles of beer"
if n == 1: return "one bottle of beer"
return str(n) + " bottles of beer"
for i in range(n, 0, -1):
print bottle(i), "on the wall,"
print bottle(i) + "."
print "Take one down, pass it around,"
print bottle(i-1), "on the wall."

View File

@ -0,0 +1,198 @@
#! /usr/bin/env python
# Fix Python source files to use the new equality test operator, i.e.,
# if x = y: ...
# is changed to
# if x == y: ...
# The script correctly tokenizes the Python program to reliably
# distinguish between assignments and equality tests.
#
# Command line arguments are files or directories to be processed.
# Directories are searched recursively for files whose name looks
# like a python module.
# Symbolic links are always ignored (except as explicit directory
# arguments). Of course, the original file is kept as a back-up
# (with a "~" attached to its name).
# It complains about binaries (files containing null bytes)
# and about files that are ostensibly not Python files: if the first
# line starts with '#!' and does not contain the string 'python'.
#
# Changes made are reported to stdout in a diff-like format.
#
# Undoubtedly you can do this using find and sed or perl, but this is
# a nice example of Python code that recurses down a directory tree
# and uses regular expressions. Also note several subtleties like
# preserving the file's mode and avoiding to even write a temp file
# when no changes are needed for a file.
#
# NB: by changing only the function fixline() you can turn this
# into a program for a different change to Python programs...
import sys
import re
import os
from stat import *
import string
err = sys.stderr.write
dbg = err
rep = sys.stdout.write
def main():
bad = 0
if not sys.argv[1:]: # No arguments
err('usage: ' + sys.argv[0] + ' file-or-directory ...\n')
sys.exit(2)
for arg in sys.argv[1:]:
if os.path.isdir(arg):
if recursedown(arg): bad = 1
elif os.path.islink(arg):
err(arg + ': will not process symbolic links\n')
bad = 1
else:
if fix(arg): bad = 1
sys.exit(bad)
ispythonprog = re.compile('^[a-zA-Z0-9_]+\.py$')
def ispython(name):
return ispythonprog.match(name) >= 0
def recursedown(dirname):
dbg('recursedown(%r)\n' % (dirname,))
bad = 0
try:
names = os.listdir(dirname)
except os.error, msg:
err('%s: cannot list directory: %r\n' % (dirname, msg))
return 1
names.sort()
subdirs = []
for name in names:
if name in (os.curdir, os.pardir): continue
fullname = os.path.join(dirname, name)
if os.path.islink(fullname): pass
elif os.path.isdir(fullname):
subdirs.append(fullname)
elif ispython(name):
if fix(fullname): bad = 1
for fullname in subdirs:
if recursedown(fullname): bad = 1
return bad
def fix(filename):
## dbg('fix(%r)\n' % (dirname,))
try:
f = open(filename, 'r')
except IOError, msg:
err('%s: cannot open: %r\n' % (filename, msg))
return 1
head, tail = os.path.split(filename)
tempname = os.path.join(head, '@' + tail)
g = None
# If we find a match, we rewind the file and start over but
# now copy everything to a temp file.
lineno = 0
while 1:
line = f.readline()
if not line: break
lineno = lineno + 1
if g is None and '\0' in line:
# Check for binary files
err(filename + ': contains null bytes; not fixed\n')
f.close()
return 1
if lineno == 1 and g is None and line[:2] == '#!':
# Check for non-Python scripts
words = string.split(line[2:])
if words and re.search('[pP]ython', words[0]) < 0:
msg = filename + ': ' + words[0]
msg = msg + ' script; not fixed\n'
err(msg)
f.close()
return 1
while line[-2:] == '\\\n':
nextline = f.readline()
if not nextline: break
line = line + nextline
lineno = lineno + 1
newline = fixline(line)
if newline != line:
if g is None:
try:
g = open(tempname, 'w')
except IOError, msg:
f.close()
err('%s: cannot create: %r\n' % (tempname, msg))
return 1
f.seek(0)
lineno = 0
rep(filename + ':\n')
continue # restart from the beginning
rep(repr(lineno) + '\n')
rep('< ' + line)
rep('> ' + newline)
if g is not None:
g.write(newline)
# End of file
f.close()
if not g: return 0 # No changes
# Finishing touch -- move files
# First copy the file's mode to the temp file
try:
statbuf = os.stat(filename)
os.chmod(tempname, statbuf[ST_MODE] & 07777)
except os.error, msg:
err('%s: warning: chmod failed (%r)\n' % (tempname, msg))
# Then make a backup of the original file as filename~
try:
os.rename(filename, filename + '~')
except os.error, msg:
err('%s: warning: backup failed (%r)\n' % (filename, msg))
# Now move the temp file to the original file
try:
os.rename(tempname, filename)
except os.error, msg:
err('%s: rename failed (%r)\n' % (filename, msg))
return 1
# Return succes
return 0
from tokenize import tokenprog
match = {'if':':', 'elif':':', 'while':':', 'return':'\n', \
'(':')', '[':']', '{':'}', '`':'`'}
def fixline(line):
# Quick check for easy case
if '=' not in line: return line
i, n = 0, len(line)
stack = []
while i < n:
j = tokenprog.match(line, i)
if j < 0:
# A bad token; forget about the rest of this line
print '(Syntax error:)'
print line,
return line
a, b = tokenprog.regs[3] # Location of the token proper
token = line[a:b]
i = i+j
if stack and token == stack[-1]:
del stack[-1]
elif match.has_key(token):
stack.append(match[token])
elif token == '=' and stack:
line = line[:a] + '==' + line[b:]
i, n = a + len('=='), len(line)
elif token == '==' and not stack:
print '(Warning: \'==\' at top level:)'
print line,
return line
if __name__ == "__main__":
main()

View File

@ -0,0 +1,49 @@
#! /usr/bin/env python
# Factorize numbers.
# The algorithm is not efficient, but easy to understand.
# If there are large factors, it will take forever to find them,
# because we try all odd numbers between 3 and sqrt(n)...
import sys
from math import sqrt
def fact(n):
if n < 1:
raise ValueError('fact() argument should be >= 1')
if n == 1:
return [] # special case
res = []
# Treat even factors special, so we can use i += 2 later
while n % 2 == 0:
res.append(2)
n //= 2
# Try odd numbers up to sqrt(n)
limit = sqrt(n+1)
i = 3
while i <= limit:
if n % i == 0:
res.append(i)
n //= i
limit = sqrt(n+1)
else:
i += 2
if n != 1:
res.append(n)
return res
def main():
if len(sys.argv) > 1:
source = sys.argv[1:]
else:
source = iter(raw_input, '')
for arg in source:
try:
n = int(arg)
except ValueError:
print arg, 'is not an integer'
else:
print n, fact(n)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,40 @@
#!/usr/bin/env python
"""
For each argument on the command line, look for it in the set of all Unicode
names. Arguments are treated as case-insensitive regular expressions, e.g.:
% find-uname 'small letter a$' 'horizontal line'
*** small letter a$ matches ***
LATIN SMALL LETTER A (97)
COMBINING LATIN SMALL LETTER A (867)
CYRILLIC SMALL LETTER A (1072)
PARENTHESIZED LATIN SMALL LETTER A (9372)
CIRCLED LATIN SMALL LETTER A (9424)
FULLWIDTH LATIN SMALL LETTER A (65345)
*** horizontal line matches ***
HORIZONTAL LINE EXTENSION (9135)
"""
import unicodedata
import sys
import re
def main(args):
unicode_names = []
for ix in range(sys.maxunicode+1):
try:
unicode_names.append((ix, unicodedata.name(unichr(ix))))
except ValueError: # no name for the character
pass
for arg in args:
pat = re.compile(arg, re.I)
matches = [(y,x) for (x,y) in unicode_names
if pat.search(y) is not None]
if matches:
print "***", arg, "matches", "***"
for match in matches:
print "%s (%d)" % match
if __name__ == "__main__":
main(sys.argv[1:])

View File

@ -0,0 +1,35 @@
#! /usr/bin/env python
# Print From and Subject of messages in $MAIL.
# Extension to multiple mailboxes and other bells & whistles are left
# as exercises for the reader.
import sys, os
# Open mailbox file. Exits with exception when this fails.
try:
mailbox = os.environ['MAIL']
except (AttributeError, KeyError):
sys.stderr.write('No environment variable $MAIL\n')
sys.exit(2)
try:
mail = open(mailbox)
except IOError:
sys.exit('Cannot open mailbox file: ' + mailbox)
while 1:
line = mail.readline()
if not line:
break # EOF
if line.startswith('From '):
# Start of message found
print line[:-1],
while 1:
line = mail.readline()
if not line or line == '\n':
break
if line.startswith('Subject: '):
print repr(line[9:-1]),
print

View File

@ -0,0 +1,102 @@
#! /usr/bin/env python
# Watch line printer queue(s).
# Intended for BSD 4.3 lpq.
import os
import sys
import time
DEF_PRINTER = 'psc'
DEF_DELAY = 10
def main():
delay = DEF_DELAY # XXX Use getopt() later
try:
thisuser = os.environ['LOGNAME']
except:
thisuser = os.environ['USER']
printers = sys.argv[1:]
if printers:
# Strip '-P' from printer names just in case
# the user specified it...
for i, name in enumerate(printers):
if name[:2] == '-P':
printers[i] = name[2:]
else:
if os.environ.has_key('PRINTER'):
printers = [os.environ['PRINTER']]
else:
printers = [DEF_PRINTER]
clearhome = os.popen('clear', 'r').read()
while True:
text = clearhome
for name in printers:
text += makestatus(name, thisuser) + '\n'
print text
time.sleep(delay)
def makestatus(name, thisuser):
pipe = os.popen('lpq -P' + name + ' 2>&1', 'r')
lines = []
users = {}
aheadbytes = 0
aheadjobs = 0
userseen = False
totalbytes = 0
totaljobs = 0
for line in pipe:
fields = line.split()
n = len(fields)
if len(fields) >= 6 and fields[n-1] == 'bytes':
rank, user, job = fields[0:3]
files = fields[3:-2]
bytes = int(fields[n-2])
if user == thisuser:
userseen = True
elif not userseen:
aheadbytes += bytes
aheadjobs += 1
totalbytes += bytes
totaljobs += 1
ujobs, ubytes = users.get(user, (0, 0))
ujobs += 1
ubytes += bytes
users[user] = ujobs, ubytes
else:
if fields and fields[0] != 'Rank':
line = line.strip()
if line == 'no entries':
line = name + ': idle'
elif line[-22:] == ' is ready and printing':
line = name
lines.append(line)
if totaljobs:
line = '%d K' % ((totalbytes+1023) // 1024)
if totaljobs != len(users):
line += ' (%d jobs)' % totaljobs
if len(users) == 1:
line += ' for %s' % (users.keys()[0],)
else:
line += ' for %d users' % len(users)
if userseen:
if aheadjobs == 0:
line += ' (%s first)' % thisuser
else:
line += ' (%d K before %s)' % (
(aheadbytes+1023) // 1024, thisuser)
lines.append(line)
sts = pipe.close()
if sts:
lines.append('lpq exit status %r' % (sts,))
return ': '.join(lines)
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
pass

View File

@ -0,0 +1,21 @@
#! /usr/bin/env python
# Like mkdir, but also make intermediate directories if necessary.
# It is not an error if the given directory already exists (as long
# as it is a directory).
# Errors are not treated specially -- you just get a Python exception.
import sys, os
def main():
for p in sys.argv[1:]:
makedirs(p)
def makedirs(p):
if p and not os.path.isdir(p):
head, tail = os.path.split(p)
makedirs(head)
os.mkdir(p, 0777)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,121 @@
#! /usr/bin/env python
class Markov:
def __init__(self, histsize, choice):
self.histsize = histsize
self.choice = choice
self.trans = {}
def add(self, state, next):
self.trans.setdefault(state, []).append(next)
def put(self, seq):
n = self.histsize
add = self.add
add(None, seq[:0])
for i in range(len(seq)):
add(seq[max(0, i-n):i], seq[i:i+1])
add(seq[len(seq)-n:], None)
def get(self):
choice = self.choice
trans = self.trans
n = self.histsize
seq = choice(trans[None])
while True:
subseq = seq[max(0, len(seq)-n):]
options = trans[subseq]
next = choice(options)
if not next:
break
seq += next
return seq
def test():
import sys, random, getopt
args = sys.argv[1:]
try:
opts, args = getopt.getopt(args, '0123456789cdwq')
except getopt.error:
print 'Usage: %s [-#] [-cddqw] [file] ...' % sys.argv[0]
print 'Options:'
print '-#: 1-digit history size (default 2)'
print '-c: characters (default)'
print '-w: words'
print '-d: more debugging output'
print '-q: no debugging output'
print 'Input files (default stdin) are split in paragraphs'
print 'separated blank lines and each paragraph is split'
print 'in words by whitespace, then reconcatenated with'
print 'exactly one space separating words.'
print 'Output consists of paragraphs separated by blank'
print 'lines, where lines are no longer than 72 characters.'
sys.exit(2)
histsize = 2
do_words = False
debug = 1
for o, a in opts:
if '-0' <= o <= '-9': histsize = int(o[1:])
if o == '-c': do_words = False
if o == '-d': debug += 1
if o == '-q': debug = 0
if o == '-w': do_words = True
if not args:
args = ['-']
m = Markov(histsize, random.choice)
try:
for filename in args:
if filename == '-':
f = sys.stdin
if f.isatty():
print 'Sorry, need stdin from file'
continue
else:
f = open(filename, 'r')
if debug: print 'processing', filename, '...'
text = f.read()
f.close()
paralist = text.split('\n\n')
for para in paralist:
if debug > 1: print 'feeding ...'
words = para.split()
if words:
if do_words:
data = tuple(words)
else:
data = ' '.join(words)
m.put(data)
except KeyboardInterrupt:
print 'Interrupted -- continue with data read so far'
if not m.trans:
print 'No valid input files'
return
if debug: print 'done.'
if debug > 1:
for key in m.trans.keys():
if key is None or len(key) < histsize:
print repr(key), m.trans[key]
if histsize == 0: print repr(''), m.trans['']
print
while True:
data = m.get()
if do_words:
words = data
else:
words = data.split()
n = 0
limit = 72
for w in words:
if n + len(w) > limit:
print
n = 0
print w,
n += len(w) + 1
print
print
if __name__ == "__main__":
test()

View File

@ -0,0 +1,124 @@
#! /usr/bin/env python
# Convert MH directories (1 message per file) or MMDF mailboxes (4x^A
# delimited) to unix mailbox (From ... delimited) on stdout.
# If -f is given, files contain one message per file (e.g. MH messages)
import rfc822
import sys
import time
import os
import stat
import getopt
import re
def main():
dofile = mmdf
try:
opts, args = getopt.getopt(sys.argv[1:], 'f')
except getopt.error, msg:
sys.stderr.write('%s\n' % msg)
sys.exit(2)
for o, a in opts:
if o == '-f':
dofile = message
if not args:
args = ['-']
sts = 0
for arg in args:
if arg == '-' or arg == '':
sts = dofile(sys.stdin) or sts
elif os.path.isdir(arg):
sts = mh(arg) or sts
elif os.path.isfile(arg):
try:
f = open(arg)
except IOError, msg:
sys.stderr.write('%s: %s\n' % (arg, msg))
sts = 1
continue
sts = dofile(f) or sts
f.close()
else:
sys.stderr.write('%s: not found\n' % arg)
sts = 1
if sts:
sys.exit(sts)
numeric = re.compile('[1-9][0-9]*')
def mh(dir):
sts = 0
msgs = os.listdir(dir)
for msg in msgs:
if numeric.match(msg) != len(msg):
continue
fn = os.path.join(dir, msg)
try:
f = open(fn)
except IOError, msg:
sys.stderr.write('%s: %s\n' % (fn, msg))
sts = 1
continue
sts = message(f) or sts
return sts
def mmdf(f):
sts = 0
while 1:
line = f.readline()
if not line:
break
if line == '\1\1\1\1\n':
sts = message(f, line) or sts
else:
sys.stderr.write(
'Bad line in MMFD mailbox: %r\n' % (line,))
return sts
counter = 0 # for generating unique Message-ID headers
def message(f, delimiter = ''):
sts = 0
# Parse RFC822 header
m = rfc822.Message(f)
# Write unix header line
fullname, email = m.getaddr('From')
tt = m.getdate('Date')
if tt:
t = time.mktime(tt)
else:
sys.stderr.write(
'Unparseable date: %r\n' % (m.getheader('Date'),))
t = os.fstat(f.fileno())[stat.ST_MTIME]
print 'From', email, time.ctime(t)
# Copy RFC822 header
for line in m.headers:
print line,
# Invent Message-ID header if none is present
if not m.has_key('message-id'):
global counter
counter = counter + 1
msgid = "<%s.%d>" % (hex(t), counter)
sys.stderr.write("Adding Message-ID %s (From %s)\n" %
(msgid, email))
print "Message-ID:", msgid
print
# Copy body
while 1:
line = f.readline()
if line == delimiter:
break
if not line:
sys.stderr.write('Unexpected EOF in message\n')
sts = 1
break
if line[:5] == 'From ':
line = '>' + line
print line,
# Print trailing newline
print
return sts
if __name__ == "__main__":
main()

View File

@ -0,0 +1,138 @@
#! /usr/bin/env python
# DAH should be three DOTs.
# Space between DOTs and DAHs should be one DOT.
# Space between two letters should be one DAH.
# Space between two words should be DOT DAH DAH.
import sys, math, audiodev
DOT = 30
DAH = 3 * DOT
OCTAVE = 2 # 1 == 441 Hz, 2 == 882 Hz, ...
morsetab = {
'A': '.-', 'a': '.-',
'B': '-...', 'b': '-...',
'C': '-.-.', 'c': '-.-.',
'D': '-..', 'd': '-..',
'E': '.', 'e': '.',
'F': '..-.', 'f': '..-.',
'G': '--.', 'g': '--.',
'H': '....', 'h': '....',
'I': '..', 'i': '..',
'J': '.---', 'j': '.---',
'K': '-.-', 'k': '-.-',
'L': '.-..', 'l': '.-..',
'M': '--', 'm': '--',
'N': '-.', 'n': '-.',
'O': '---', 'o': '---',
'P': '.--.', 'p': '.--.',
'Q': '--.-', 'q': '--.-',
'R': '.-.', 'r': '.-.',
'S': '...', 's': '...',
'T': '-', 't': '-',
'U': '..-', 'u': '..-',
'V': '...-', 'v': '...-',
'W': '.--', 'w': '.--',
'X': '-..-', 'x': '-..-',
'Y': '-.--', 'y': '-.--',
'Z': '--..', 'z': '--..',
'0': '-----', ',': '--..--',
'1': '.----', '.': '.-.-.-',
'2': '..---', '?': '..--..',
'3': '...--', ';': '-.-.-.',
'4': '....-', ':': '---...',
'5': '.....', "'": '.----.',
'6': '-....', '-': '-....-',
'7': '--...', '/': '-..-.',
'8': '---..', '(': '-.--.-',
'9': '----.', ')': '-.--.-',
' ': ' ', '_': '..--.-',
}
nowave = '\0' * 200
# If we play at 44.1 kHz (which we do), then if we produce one sine
# wave in 100 samples, we get a tone of 441 Hz. If we produce two
# sine waves in these 100 samples, we get a tone of 882 Hz. 882 Hz
# appears to be a nice one for playing morse code.
def mkwave(octave):
sinewave = ''
for i in range(100):
val = int(math.sin(math.pi * i * octave / 50.0) * 30000)
sinewave += chr((val >> 8) & 255) + chr(val & 255)
return sinewave
defaultwave = mkwave(OCTAVE)
def main():
import getopt
try:
opts, args = getopt.getopt(sys.argv[1:], 'o:p:')
except getopt.error:
sys.stderr.write('Usage ' + sys.argv[0] +
' [ -o outfile ] [ -p octave ] [ words ] ...\n')
sys.exit(1)
dev = None
wave = defaultwave
for o, a in opts:
if o == '-o':
import aifc
dev = aifc.open(a, 'w')
dev.setframerate(44100)
dev.setsampwidth(2)
dev.setnchannels(1)
if o == '-p':
wave = mkwave(int(a))
if not dev:
import audiodev
dev = audiodev.AudioDev()
dev.setoutrate(44100)
dev.setsampwidth(2)
dev.setnchannels(1)
dev.close = dev.stop
dev.writeframesraw = dev.writeframes
if args:
source = [' '.join(args)]
else:
source = iter(sys.stdin.readline, '')
for line in source:
mline = morse(line)
play(mline, dev, wave)
if hasattr(dev, 'wait'):
dev.wait()
dev.close()
# Convert a string to morse code with \001 between the characters in
# the string.
def morse(line):
res = ''
for c in line:
try:
res += morsetab[c] + '\001'
except KeyError:
pass
return res
# Play a line of morse code.
def play(line, dev, wave):
for c in line:
if c == '.':
sine(dev, DOT, wave)
elif c == '-':
sine(dev, DAH, wave)
else: # space
pause(dev, DAH + DOT)
pause(dev, DOT)
def sine(dev, length, wave):
for i in range(length):
dev.writeframesraw(wave)
def pause(dev, length):
for i in range(length):
dev.writeframesraw(nowave)
if __name__ == '__main__':
main()

View File

@ -0,0 +1,59 @@
NEWSLIST
========
A program to assist HTTP browsing of newsgroups
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
WWW browsers such as NCSA Mosaic allow the user to read newsgroup
articles by specifying the group name in a URL eg 'news:comp.answers'.
To browse through many groups, though, (and there are several thousand
of them) you really need a page or pages containing links to all the
groups. There are some good ones out there, for example,
http://info.cern.ch/hypertext/DataSources/News/Groups/Overview.html
is the standard one at CERN, but it only shows the groups available there,
which may be rather different from those available on your machine.
Newslist is a program which creates a hierarchy of pages for you based
on the groups available from YOUR server. It is written in python - a
splendid interpreted object-oriented language which I suggest you get
right now from the directory /pub/python at ftp.cwi.nl, if you haven't
already got it.
You should be able to see some sample output by looking at:
http://pelican.cl.cam.ac.uk/newspage/root.html
Descriptions of newsgroups can be added from a file with one group
per line. eg:
alt.foo Articles about foo
comp.bar Programming in 'bar' and related languages
A suitable list detailing most groups can be found at ftp.uu.net in
/uunet-info/newsgroups.gz.
Make sure you read the information at the beginning of the program source and
configure the variables before running.
In addition to python, you need:
An NNTP-based news feed.
A directory in which to put the pages.
The programming is not very beautiful, but it works! It comes with no
warranty, express or implied, but with the hope that some others may
find it useful.
Comments, improvements & suggestions welcomed.
Quentin Stafford-Fraser
----------------------------------------------------------------------
Quentin Stafford-Fraser
http://pelican.cl.cam.ac.uk/people/qs101/me.html
Cambridge University Computer Lab Rank Xerox Cambridge EuroPARC
qs101@cl.cam.ac.uk fraser@europarc.xerox.com
Tel: +44 223 334411 Tel: +44 223 341521
Fax: +44 223 334679 Fax: +44 223 341510
----------------------------------------------------------------------

View File

@ -0,0 +1,362 @@
#! /usr/bin/env python
#######################################################################
# Newslist $Revision$
#
# Syntax:
# newslist [ -a ]
#
# This is a program to create a directory full of HTML pages
# which between them contain links to all the newsgroups available
# on your server.
#
# The -a option causes a complete list of all groups to be read from
# the server rather than just the ones which have appeared since last
# execution. This recreates the local list from scratch. Use this on
# the first invocation of the program, and from time to time thereafter.
# When new groups are first created they may appear on your server as
# empty groups. By default, empty groups are ignored by the -a option.
# However, these new groups will not be created again, and so will not
# appear in the server's list of 'new groups' at a later date. Hence it
# won't appear until you do a '-a' after some articles have appeared.
#
# I should really keep a list of ignored empty groups and re-check them
# for articles on every run, but I haven't got around to it yet.
#
# This assumes an NNTP news feed.
#
# Feel free to copy, distribute and modify this code for
# non-commercial use. If you make any useful modifications, let me
# know!
#
# (c) Quentin Stafford-Fraser 1994
# fraser@europarc.xerox.com qs101@cl.cam.ac.uk
# #
#######################################################################
import sys, nntplib, marshal, time, os
#######################################################################
# Check these variables before running! #
# Top directory.
# Filenames which don't start with / are taken as being relative to this.
topdir = os.path.expanduser('~/newspage')
# The name of your NNTP host
# eg.
# newshost = 'nntp-serv.cl.cam.ac.uk'
# or use following to get the name from the NNTPSERVER environment
# variable:
# newshost = os.environ['NNTPSERVER']
newshost = 'news.example.com'
# The filename for a local cache of the newsgroup list
treefile = 'grouptree'
# The filename for descriptions of newsgroups
# I found a suitable one at ftp.uu.net in /uunet-info/newgroups.gz
# You can set this to '' if you don't wish to use one.
descfile = 'newsgroups'
# The directory in which HTML pages should be created
# eg.
# pagedir = '/usr/local/lib/html/newspage'
# pagedir = 'pages'
pagedir = topdir
# The html prefix which will refer to this directory
# eg.
# httppref = '/newspage/',
# or leave blank for relative links between pages: (Recommended)
# httppref = ''
httppref = ''
# The name of the 'root' news page in this directory.
# A .html suffix will be added.
rootpage = 'root'
# Set skipempty to 0 if you wish to see links to empty groups as well.
# Only affects the -a option.
skipempty = 1
# pagelinkicon can contain html to put an icon after links to
# further pages. This helps to make important links stand out.
# Set to '' if not wanted, or '...' is quite a good one.
pagelinkicon = '... <img src="http://pelican.cl.cam.ac.uk/icons/page.xbm"> '
# ---------------------------------------------------------------------
# Less important personal preferences:
# Sublistsize controls the maximum number of items the will appear as
# an indented sub-list before the whole thing is moved onto a different
# page. The smaller this is, the more pages you will have, but the
# shorter each will be.
sublistsize = 4
# That should be all. #
#######################################################################
for dir in os.curdir, os.environ['HOME']:
rcfile = os.path.join(dir, '.newslistrc.py')
if os.path.exists(rcfile):
print rcfile
execfile(rcfile)
break
from nntplib import NNTP
from stat import *
rcsrev = '$Revision$'
rcsrev = ' '.join(filter(lambda s: '$' not in s, rcsrev.split()))
desc = {}
# Make (possibly) relative filenames into absolute ones
treefile = os.path.join(topdir,treefile)
descfile = os.path.join(topdir,descfile)
page = os.path.join(topdir,pagedir)
# First the bits for creating trees ---------------------------
# Addtotree creates/augments a tree from a list of group names
def addtotree(tree, groups):
print 'Updating tree...'
for i in groups:
parts = i.split('.')
makeleaf(tree, parts)
# Makeleaf makes a leaf and the branch leading to it if necessary
def makeleaf(tree,path):
j = path[0]
l = len(path)
if j not in tree:
tree[j] = {}
if l == 1:
tree[j]['.'] = '.'
if l > 1:
makeleaf(tree[j],path[1:])
# Then the bits for outputting trees as pages ----------------
# Createpage creates an HTML file named <root>.html containing links
# to those groups beginning with <root>.
def createpage(root, tree, p):
filename = os.path.join(pagedir, root+'.html')
if root == rootpage:
detail = ''
else:
detail = ' under ' + root
with open(filename, 'w') as f:
# f.write('Content-Type: text/html\n')
f.write('<html>\n<head>\n')
f.write('<title>Newsgroups available%s</title>\n' % detail)
f.write('</head>\n<body>\n')
f.write('<h1>Newsgroups available%s</h1>\n' % detail)
f.write('<a href="%s%s.html">Back to top level</a><p>\n' %
(httppref, rootpage))
printtree(f, tree, 0, p)
f.write('\n<p>')
f.write("<i>This page automatically created by 'newslist' v. %s." %
rcsrev)
f.write(time.ctime(time.time()) + '</i>\n')
f.write('</body>\n</html>\n')
# Printtree prints the groups as a bulleted list. Groups with
# more than <sublistsize> subgroups will be put on a separate page.
# Other sets of subgroups are just indented.
def printtree(f, tree, indent, p):
l = len(tree)
if l > sublistsize and indent > 0:
# Create a new page and a link to it
f.write('<li><b><a href="%s%s.html">' % (httppref, p[1:]))
f.write(p[1:] + '.*')
f.write('</a></b>%s\n' % pagelinkicon)
createpage(p[1:], tree, p)
return
kl = tree.keys()
if l > 1:
kl.sort()
if indent > 0:
# Create a sub-list
f.write('<li>%s\n<ul>' % p[1:])
else:
# Create a main list
f.write('<ul>')
indent = indent + 1
for i in kl:
if i == '.':
# Output a newsgroup
f.write('<li><a href="news:%s">%s</a> ' % (p[1:], p[1:]))
if p[1:] in desc:
f.write(' <i>%s</i>\n' % desc[p[1:]])
else:
f.write('\n')
else:
# Output a hierarchy
printtree(f, tree[i], indent, p+'.'+i)
if l > 1:
f.write('\n</ul>')
# Reading descriptions file ---------------------------------------
# This returns a dict mapping group name to its description
def readdesc(descfile):
global desc
desc = {}
if descfile == '':
return
try:
with open(descfile, 'r') as d:
print 'Reading descriptions...'
for l in d:
bits = l.split()
try:
grp = bits[0]
dsc = ' '.join(bits[1:])
if len(dsc) > 1:
desc[grp] = dsc
except IndexError:
pass
except IOError:
print 'Failed to open description file ' + descfile
return
# Check that ouput directory exists, ------------------------------
# and offer to create it if not
def checkopdir(pagedir):
if not os.path.isdir(pagedir):
print 'Directory %s does not exist.' % pagedir
print 'Shall I create it for you? (y/n)'
if sys.stdin.readline()[0] == 'y':
try:
os.mkdir(pagedir, 0777)
except:
print 'Sorry - failed!'
sys.exit(1)
else:
print 'OK. Exiting.'
sys.exit(1)
# Read and write current local tree ----------------------------------
def readlocallist(treefile):
print 'Reading current local group list...'
tree = {}
try:
treetime = time.localtime(os.stat(treefile)[ST_MTIME])
except:
print '\n*** Failed to open local group cache '+treefile
print 'If this is the first time you have run newslist, then'
print 'use the -a option to create it.'
sys.exit(1)
treedate = '%02d%02d%02d' % (treetime[0] % 100, treetime[1], treetime[2])
try:
with open(treefile, 'rb') as dump:
tree = marshal.load(dump)
except IOError:
print 'Cannot open local group list ' + treefile
return (tree, treedate)
def writelocallist(treefile, tree):
try:
with open(treefile, 'wb') as dump:
groups = marshal.dump(tree, dump)
print 'Saved list to %s\n' % treefile
except:
print 'Sorry - failed to write to local group cache', treefile
print 'Does it (or its directory) have the correct permissions?'
sys.exit(1)
# Return list of all groups on server -----------------------------
def getallgroups(server):
print 'Getting list of all groups...'
treedate = '010101'
info = server.list()[1]
groups = []
print 'Processing...'
if skipempty:
print '\nIgnoring following empty groups:'
for i in info:
grpname = i[0].split()[0]
if skipempty and int(i[1]) < int(i[2]):
print grpname + ' ',
else:
groups.append(grpname)
print '\n'
if skipempty:
print '(End of empty groups)'
return groups
# Return list of new groups on server -----------------------------
def getnewgroups(server, treedate):
print 'Getting list of new groups since start of %s...' % treedate,
info = server.newgroups(treedate, '000001')[1]
print 'got %d.' % len(info)
print 'Processing...',
groups = []
for i in info:
grpname = i.split()[0]
groups.append(grpname)
print 'Done'
return groups
# Now the main program --------------------------------------------
def main():
tree = {}
# Check that the output directory exists
checkopdir(pagedir)
try:
print 'Connecting to %s...' % newshost
if sys.version[0] == '0':
s = NNTP.init(newshost)
else:
s = NNTP(newshost)
connected = True
except (nntplib.error_temp, nntplib.error_perm), x:
print 'Error connecting to host:', x
print 'I\'ll try to use just the local list.'
connected = False
# If -a is specified, read the full list of groups from server
if connected and len(sys.argv) > 1 and sys.argv[1] == '-a':
groups = getallgroups(s)
# Otherwise just read the local file and then add
# groups created since local file last modified.
else:
(tree, treedate) = readlocallist(treefile)
if connected:
groups = getnewgroups(s, treedate)
if connected:
addtotree(tree, groups)
writelocallist(treefile,tree)
# Read group descriptions
readdesc(descfile)
print 'Creating pages...'
createpage(rootpage, tree, '')
print 'Done'
if __name__ == "__main__":
main()
# That's all folks
######################################################################

View File

@ -0,0 +1,33 @@
#! /usr/bin/env python
# Print digits of pi forever.
#
# The algorithm, using Python's 'long' integers ("bignums"), works
# with continued fractions, and was conceived by Lambert Meertens.
#
# See also the ABC Programmer's Handbook, by Geurts, Meertens & Pemberton,
# published by Prentice-Hall (UK) Ltd., 1990.
import sys
def main():
k, a, b, a1, b1 = 2, 4, 1, 12, 4
while True:
# Next approximation
p, q, k = k*k, 2*k+1, k+1
a, b, a1, b1 = a1, b1, p*a+q*a1, p*b+q*b1
# Print common digits
d, d1 = a//b, a1//b1
while d == d1:
output(d)
a, a1 = 10*(a%b), 10*(a1%b1)
d, d1 = a//b, a1//b1
def output(d):
# Use write() to avoid spaces between the digits
sys.stdout.write(str(d))
# Flush so the output is seen immediately
sys.stdout.flush()
if __name__ == "__main__":
main()

View File

@ -0,0 +1,129 @@
#! /usr/bin/env python
# Emulate some Perl command line options.
# Usage: pp [-a] [-c] [-d] [-e scriptline] [-F fieldsep] [-n] [-p] [file] ...
# Where the options mean the following:
# -a : together with -n or -p, splits each line into list F
# -c : check syntax only, do not execute any code
# -d : run the script under the debugger, pdb
# -e scriptline : gives one line of the Python script; may be repeated
# -F fieldsep : sets the field separator for the -a option [not in Perl]
# -n : runs the script for each line of input
# -p : prints the line after the script has run
# When no script lines have been passed, the first file argument
# contains the script. With -n or -p, the remaining arguments are
# read as input to the script, line by line. If a file is '-'
# or missing, standard input is read.
# XXX To do:
# - add -i extension option (change files in place)
# - make a single loop over the files and lines (changes effect of 'break')?
# - add an option to specify the record separator
# - except for -n/-p, run directly from the file if at all possible
import sys
import getopt
FS = ''
SCRIPT = []
AFLAG = 0
CFLAG = 0
DFLAG = 0
NFLAG = 0
PFLAG = 0
try:
optlist, ARGS = getopt.getopt(sys.argv[1:], 'acde:F:np')
except getopt.error, msg:
sys.stderr.write('%s: %s\n' % (sys.argv[0], msg))
sys.exit(2)
for option, optarg in optlist:
if option == '-a':
AFLAG = 1
elif option == '-c':
CFLAG = 1
elif option == '-d':
DFLAG = 1
elif option == '-e':
for line in optarg.split('\n'):
SCRIPT.append(line)
elif option == '-F':
FS = optarg
elif option == '-n':
NFLAG = 1
PFLAG = 0
elif option == '-p':
NFLAG = 1
PFLAG = 1
else:
print option, 'not recognized???'
if not ARGS: ARGS.append('-')
if not SCRIPT:
if ARGS[0] == '-':
fp = sys.stdin
else:
fp = open(ARGS[0], 'r')
while 1:
line = fp.readline()
if not line: break
SCRIPT.append(line[:-1])
del fp
del ARGS[0]
if not ARGS: ARGS.append('-')
if CFLAG:
prologue = ['if 0:']
epilogue = []
elif NFLAG:
# Note that it is on purpose that AFLAG and PFLAG are
# tested dynamically each time through the loop
prologue = [
'LINECOUNT = 0',
'for FILE in ARGS:',
' \tif FILE == \'-\':',
' \t \tFP = sys.stdin',
' \telse:',
' \t \tFP = open(FILE, \'r\')',
' \tLINENO = 0',
' \twhile 1:',
' \t \tLINE = FP.readline()',
' \t \tif not LINE: break',
' \t \tLINENO = LINENO + 1',
' \t \tLINECOUNT = LINECOUNT + 1',
' \t \tL = LINE[:-1]',
' \t \taflag = AFLAG',
' \t \tif aflag:',
' \t \t \tif FS: F = L.split(FS)',
' \t \t \telse: F = L.split()'
]
epilogue = [
' \t \tif not PFLAG: continue',
' \t \tif aflag:',
' \t \t \tif FS: print FS.join(F)',
' \t \t \telse: print \' \'.join(F)',
' \t \telse: print L',
]
else:
prologue = ['if 1:']
epilogue = []
# Note that we indent using tabs only, so that any indentation style
# used in 'command' will come out right after re-indentation.
program = '\n'.join(prologue) + '\n'
for line in SCRIPT:
program += ' \t \t' + line + '\n'
program += '\n'.join(epilogue) + '\n'
import tempfile
fp = tempfile.NamedTemporaryFile()
fp.write(program)
fp.flush()
if DFLAG:
import pdb
pdb.run('execfile(%r)' % (fp.name,))
else:
execfile(fp.name)

View File

@ -0,0 +1,30 @@
#! /usr/bin/env python
# Print prime numbers in a given range
def primes(min, max):
if max >= 2 >= min:
print 2
primes = [2]
i = 3
while i <= max:
for p in primes:
if i % p == 0 or p*p > i:
break
if i % p != 0:
primes.append(i)
if i >= min:
print i
i += 2
def main():
import sys
min, max = 2, 0x7fffffff
if sys.argv[1:]:
min = int(sys.argv[1])
if sys.argv[2:]:
max = int(sys.argv[2])
primes(min, max)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,85 @@
#! /usr/bin/env python
"""N queens problem.
The (well-known) problem is due to Niklaus Wirth.
This solution is inspired by Dijkstra (Structured Programming). It is
a classic recursive backtracking approach.
"""
N = 8 # Default; command line overrides
class Queens:
def __init__(self, n=N):
self.n = n
self.reset()
def reset(self):
n = self.n
self.y = [None] * n # Where is the queen in column x
self.row = [0] * n # Is row[y] safe?
self.up = [0] * (2*n-1) # Is upward diagonal[x-y] safe?
self.down = [0] * (2*n-1) # Is downward diagonal[x+y] safe?
self.nfound = 0 # Instrumentation
def solve(self, x=0): # Recursive solver
for y in range(self.n):
if self.safe(x, y):
self.place(x, y)
if x+1 == self.n:
self.display()
else:
self.solve(x+1)
self.remove(x, y)
def safe(self, x, y):
return not self.row[y] and not self.up[x-y] and not self.down[x+y]
def place(self, x, y):
self.y[x] = y
self.row[y] = 1
self.up[x-y] = 1
self.down[x+y] = 1
def remove(self, x, y):
self.y[x] = None
self.row[y] = 0
self.up[x-y] = 0
self.down[x+y] = 0
silent = 0 # If true, count solutions only
def display(self):
self.nfound = self.nfound + 1
if self.silent:
return
print '+-' + '--'*self.n + '+'
for y in range(self.n-1, -1, -1):
print '|',
for x in range(self.n):
if self.y[x] == y:
print "Q",
else:
print ".",
print '|'
print '+-' + '--'*self.n + '+'
def main():
import sys
silent = 0
n = N
if sys.argv[1:2] == ['-n']:
silent = 1
del sys.argv[1]
if sys.argv[1:]:
n = int(sys.argv[1])
q = Queens(n)
q.silent = silent
q.solve()
print "Found", q.nfound, "solutions."
if __name__ == "__main__":
main()

View File

@ -0,0 +1,42 @@
#! /usr/bin/env python
# script.py -- Make typescript of terminal session.
# Usage:
# -a Append to typescript.
# -p Use Python as shell.
# Author: Steen Lumholt.
import os, time, sys, getopt
import pty
def read(fd):
data = os.read(fd, 1024)
script.write(data)
return data
shell = 'sh'
filename = 'typescript'
mode = 'w'
if os.environ.has_key('SHELL'):
shell = os.environ['SHELL']
try:
opts, args = getopt.getopt(sys.argv[1:], 'ap')
except getopt.error, msg:
print '%s: %s' % (sys.argv[0], msg)
sys.exit(2)
for o, a in opts:
if o == '-a':
mode = 'a'
elif o == '-p':
shell = 'python'
script = open(filename, mode)
sys.stdout.write('Script started, file is %s\n' % filename)
script.write('Script started on %s\n' % time.ctime(time.time()))
pty.spawn(shell, read)
script.write('Script done on %s\n' % time.ctime(time.time()))
sys.stdout.write('Script done, file is %s\n' % filename)

View File

@ -0,0 +1,104 @@
#! /usr/bin/env python
# Calculate your unbirthday count (see Alice in Wonderland).
# This is defined as the number of days from your birth until today
# that weren't your birthday. (The day you were born is not counted).
# Leap years make it interesting.
import sys
import time
import calendar
def main():
if sys.argv[1:]:
year = int(sys.argv[1])
else:
year = int(raw_input('In which year were you born? '))
if 0 <= year < 100:
print "I'll assume that by", year,
year = year + 1900
print 'you mean', year, 'and not the early Christian era'
elif not (1850 <= year <= time.localtime()[0]):
print "It's hard to believe you were born in", year
return
if sys.argv[2:]:
month = int(sys.argv[2])
else:
month = int(raw_input('And in which month? (1-12) '))
if not (1 <= month <= 12):
print 'There is no month numbered', month
return
if sys.argv[3:]:
day = int(sys.argv[3])
else:
day = int(raw_input('And on what day of that month? (1-31) '))
if month == 2 and calendar.isleap(year):
maxday = 29
else:
maxday = calendar.mdays[month]
if not (1 <= day <= maxday):
print 'There are no', day, 'days in that month!'
return
bdaytuple = (year, month, day)
bdaydate = mkdate(bdaytuple)
print 'You were born on', format(bdaytuple)
todaytuple = time.localtime()[:3]
todaydate = mkdate(todaytuple)
print 'Today is', format(todaytuple)
if bdaytuple > todaytuple:
print 'You are a time traveler. Go back to the future!'
return
if bdaytuple == todaytuple:
print 'You were born today. Have a nice life!'
return
days = todaydate - bdaydate
print 'You have lived', days, 'days'
age = 0
for y in range(year, todaytuple[0] + 1):
if bdaytuple < (y, month, day) <= todaytuple:
age = age + 1
print 'You are', age, 'years old'
if todaytuple[1:] == bdaytuple[1:]:
print 'Congratulations! Today is your', nth(age), 'birthday'
print 'Yesterday was your',
else:
print 'Today is your',
print nth(days - age), 'unbirthday'
def format((year, month, day)):
return '%d %s %d' % (day, calendar.month_name[month], year)
def nth(n):
if n == 1: return '1st'
if n == 2: return '2nd'
if n == 3: return '3rd'
return '%dth' % n
def mkdate((year, month, day)):
# January 1st, in 0 A.D. is arbitrarily defined to be day 1,
# even though that day never actually existed and the calendar
# was different then...
days = year*365 # years, roughly
days = days + (year+3)//4 # plus leap years, roughly
days = days - (year+99)//100 # minus non-leap years every century
days = days + (year+399)//400 # plus leap years every 4 centirues
for i in range(1, month):
if i == 2 and calendar.isleap(year):
days = days + 29
else:
days = days + calendar.mdays[i]
days = days + day
return days
if __name__ == "__main__":
main()

View File

@ -0,0 +1,92 @@
#! /usr/bin/env python
# Update a bunch of files according to a script.
# The input file contains lines of the form <filename>:<lineno>:<text>,
# meaning that the given line of the given file is to be replaced
# by the given text. This is useful for performing global substitutions
# on grep output:
import os
import sys
import re
pat = '^([^: \t\n]+):([1-9][0-9]*):'
prog = re.compile(pat)
class FileObj:
def __init__(self, filename):
self.filename = filename
self.changed = 0
try:
self.lines = open(filename, 'r').readlines()
except IOError, msg:
print '*** Can\'t open "%s":' % filename, msg
self.lines = None
return
print 'diffing', self.filename
def finish(self):
if not self.changed:
print 'no changes to', self.filename
return
try:
os.rename(self.filename, self.filename + '~')
fp = open(self.filename, 'w')
except (os.error, IOError), msg:
print '*** Can\'t rewrite "%s":' % self.filename, msg
return
print 'writing', self.filename
for line in self.lines:
fp.write(line)
fp.close()
self.changed = 0
def process(self, lineno, rest):
if self.lines is None:
print '(not processed): %s:%s:%s' % (
self.filename, lineno, rest),
return
i = eval(lineno) - 1
if not 0 <= i < len(self.lines):
print '*** Line number out of range: %s:%s:%s' % (
self.filename, lineno, rest),
return
if self.lines[i] == rest:
print '(no change): %s:%s:%s' % (
self.filename, lineno, rest),
return
if not self.changed:
self.changed = 1
print '%sc%s' % (lineno, lineno)
print '<', self.lines[i],
print '---'
self.lines[i] = rest
print '>', self.lines[i],
def main():
if sys.argv[1:]:
try:
fp = open(sys.argv[1], 'r')
except IOError, msg:
print 'Can\'t open "%s":' % sys.argv[1], msg
sys.exit(1)
else:
fp = sys.stdin
curfile = None
while 1:
line = fp.readline()
if not line:
if curfile: curfile.finish()
break
n = prog.match(line)
if n < 0:
print 'Funny line:', line,
continue
filename, lineno = prog.group(1, 2)
if not curfile or filename <> curfile.filename:
if curfile: curfile.finish()
curfile = FileObj(filename)
curfile.process(lineno, line[n:])
if __name__ == "__main__":
main()