History

add hg and python

cinap_lenrek committed 15 years ago

Commit 4bb9e221 parent 987265c3706 files · +1228772 −-233Browse files

Showing the changes to sys/src/cmd/python/Demo/scripts (23 of 3706 files). Show all

Unified · Split

23 files
  1. sys/src/cmd/python/Demo/scripts/README +23 −0
  2. sys/src/cmd/python/Demo/scripts/beer.py +14 −0
  3. sys/src/cmd/python/Demo/scripts/eqfix.py +198 −0
  4. sys/src/cmd/python/Demo/scripts/fact.py +49 −0
  5. sys/src/cmd/python/Demo/scripts/find-uname.py +40 −0
  6. sys/src/cmd/python/Demo/scripts/from.py +35 −0
  7. sys/src/cmd/python/Demo/scripts/ftpstats.py +145 −0
  8. sys/src/cmd/python/Demo/scripts/lpwatch.py +110 −0
  9. sys/src/cmd/python/Demo/scripts/makedir.py +21 −0
  10. sys/src/cmd/python/Demo/scripts/markov.py +117 −0
  11. sys/src/cmd/python/Demo/scripts/mboxconvert.py +124 −0
  12. sys/src/cmd/python/Demo/scripts/mkrcs.py +61 −0
  13. sys/src/cmd/python/Demo/scripts/morse.py +149 −0
  14. sys/src/cmd/python/Demo/scripts/newslist.doc +59 −0
  15. sys/src/cmd/python/Demo/scripts/newslist.py +366 −0
  16. sys/src/cmd/python/Demo/scripts/pi.py +34 −0
  17. sys/src/cmd/python/Demo/scripts/pp.py +130 −0
  18. sys/src/cmd/python/Demo/scripts/primes.py +27 −0
  19. sys/src/cmd/python/Demo/scripts/queens.py +85 −0
  20. sys/src/cmd/python/Demo/scripts/script.py +33 −0
  21. sys/src/cmd/python/Demo/scripts/unbirthday.py +107 −0
  22. sys/src/cmd/python/Demo/scripts/update.py +92 −0
  23. sys/src/cmd/python/Demo/scripts/wh.py +2 −0
sys/src/cmd/python/Demo/scripts/README+23−0
@@ -0,0 +1,23 @@
1+This directory contains a collection of executable Python scripts.
2+
3+See also the Tools/scripts directory!
4+
5+beer.py Print the classic 'bottles of beer' list.
6+eqfix.py Fix .py files to use the correct equality test operator
7+fact.py Factorize numbers
8+find-uname.py Search for Unicode characters using regexps.
9+from.py Summarize mailbox
10+ftpstats.py Summarize ftp daemon log file
11+lpwatch.py Watch BSD line printer queues
12+makedir.py Like mkdir -p
13+markov.py Markov chain simulation of words or characters
14+mboxconvvert.py Convert MH or MMDF mailboxes to unix mailbox format
15+mkrcs.py Fix symlinks named RCS into parallel tree
16+morse.py Produce morse code (audible or on AIFF file)
17+pi.py Print all digits of pi -- given enough time and memory
18+pp.py Emulate some Perl command line options
19+primes.py Print prime numbers
20+queens.py Dijkstra's solution to Wirth's "N Queens problem"
21+script.py Equivalent to BSD script(1) -- by Steen Lumholt
22+unbirthday.py Print unbirthday count
23+update.py Update a bunch of files according to a script.
sys/src/cmd/python/Demo/scripts/beer.py+14−0
@@ -0,0 +1,14 @@
1+#! /usr/bin/env python
2+# By GvR, demystified after a version by Fredrik Lundh.
3+import sys
4+n = 100
5+if sys.argv[1:]: n = int(sys.argv[1])
6+def bottle(n):
7+ if n == 0: return "no more bottles of beer"
8+ if n == 1: return "one bottle of beer"
9+ return str(n) + " bottles of beer"
10+for i in range(n):
11+ print bottle(n-i), "on the wall,"
12+ print bottle(n-i) + "."
13+ print "Take one down, pass it around,"
14+ print bottle(n-i-1), "on the wall."
sys/src/cmd/python/Demo/scripts/eqfix.py+198−0
@@ -0,0 +1,198 @@
1+#! /usr/bin/env python
2+
3+# Fix Python source files to use the new equality test operator, i.e.,
4+# if x = y: ...
5+# is changed to
6+# if x == y: ...
7+# The script correctly tokenizes the Python program to reliably
8+# distinguish between assignments and equality tests.
9+#
10+# Command line arguments are files or directories to be processed.
11+# Directories are searched recursively for files whose name looks
12+# like a python module.
13+# Symbolic links are always ignored (except as explicit directory
14+# arguments). Of course, the original file is kept as a back-up
15+# (with a "~" attached to its name).
16+# It complains about binaries (files containing null bytes)
17+# and about files that are ostensibly not Python files: if the first
18+# line starts with '#!' and does not contain the string 'python'.
19+#
20+# Changes made are reported to stdout in a diff-like format.
21+#
22+# Undoubtedly you can do this using find and sed or perl, but this is
23+# a nice example of Python code that recurses down a directory tree
24+# and uses regular expressions. Also note several subtleties like
25+# preserving the file's mode and avoiding to even write a temp file
26+# when no changes are needed for a file.
27+#
28+# NB: by changing only the function fixline() you can turn this
29+# into a program for a different change to Python programs...
30+
31+import sys
32+import re
33+import os
34+from stat import *
35+import string
36+
37+err = sys.stderr.write
38+dbg = err
39+rep = sys.stdout.write
40+
41+def main():
42+ bad = 0
43+ if not sys.argv[1:]: # No arguments
44+ err('usage: ' + sys.argv[0] + ' file-or-directory ...\n')
45+ sys.exit(2)
46+ for arg in sys.argv[1:]:
47+ if os.path.isdir(arg):
48+ if recursedown(arg): bad = 1
49+ elif os.path.islink(arg):
50+ err(arg + ': will not process symbolic links\n')
51+ bad = 1
52+ else:
53+ if fix(arg): bad = 1
54+ sys.exit(bad)
55+
56+ispythonprog = re.compile('^[a-zA-Z0-9_]+\.py$')
57+def ispython(name):
58+ return ispythonprog.match(name) >= 0
59+
60+def recursedown(dirname):
61+ dbg('recursedown(%r)\n' % (dirname,))
62+ bad = 0
63+ try:
64+ names = os.listdir(dirname)
65+ except os.error, msg:
66+ err('%s: cannot list directory: %r\n' % (dirname, msg))
67+ return 1
68+ names.sort()
69+ subdirs = []
70+ for name in names:
71+ if name in (os.curdir, os.pardir): continue
72+ fullname = os.path.join(dirname, name)
73+ if os.path.islink(fullname): pass
74+ elif os.path.isdir(fullname):
75+ subdirs.append(fullname)
76+ elif ispython(name):
77+ if fix(fullname): bad = 1
78+ for fullname in subdirs:
79+ if recursedown(fullname): bad = 1
80+ return bad
81+
82+def fix(filename):
83+## dbg('fix(%r)\n' % (dirname,))
84+ try:
85+ f = open(filename, 'r')
86+ except IOError, msg:
87+ err('%s: cannot open: %r\n' % (filename, msg))
88+ return 1
89+ head, tail = os.path.split(filename)
90+ tempname = os.path.join(head, '@' + tail)
91+ g = None
92+ # If we find a match, we rewind the file and start over but
93+ # now copy everything to a temp file.
94+ lineno = 0
95+ while 1:
96+ line = f.readline()
97+ if not line: break
98+ lineno = lineno + 1
99+ if g is None and '\0' in line:
100+ # Check for binary files
101+ err(filename + ': contains null bytes; not fixed\n')
102+ f.close()
103+ return 1
104+ if lineno == 1 and g is None and line[:2] == '#!':
105+ # Check for non-Python scripts
106+ words = string.split(line[2:])
107+ if words and re.search('[pP]ython', words[0]) < 0:
108+ msg = filename + ': ' + words[0]
109+ msg = msg + ' script; not fixed\n'
110+ err(msg)
111+ f.close()
112+ return 1
113+ while line[-2:] == '\\\n':
114+ nextline = f.readline()
115+ if not nextline: break
116+ line = line + nextline
117+ lineno = lineno + 1
118+ newline = fixline(line)
119+ if newline != line:
120+ if g is None:
121+ try:
122+ g = open(tempname, 'w')
123+ except IOError, msg:
124+ f.close()
125+ err('%s: cannot create: %r\n' % (tempname, msg))
126+ return 1
127+ f.seek(0)
128+ lineno = 0
129+ rep(filename + ':\n')
130+ continue # restart from the beginning
131+ rep(repr(lineno) + '\n')
132+ rep('< ' + line)
133+ rep('> ' + newline)
134+ if g is not None:
135+ g.write(newline)
136+
137+ # End of file
138+ f.close()
139+ if not g: return 0 # No changes
140+
141+ # Finishing touch -- move files
142+
143+ # First copy the file's mode to the temp file
144+ try:
145+ statbuf = os.stat(filename)
146+ os.chmod(tempname, statbuf[ST_MODE] & 07777)
147+ except os.error, msg:
148+ err('%s: warning: chmod failed (%r)\n' % (tempname, msg))
149+ # Then make a backup of the original file as filename~
150+ try:
151+ os.rename(filename, filename + '~')
152+ except os.error, msg:
153+ err('%s: warning: backup failed (%r)\n' % (filename, msg))
154+ # Now move the temp file to the original file
155+ try:
156+ os.rename(tempname, filename)
157+ except os.error, msg:
158+ err('%s: rename failed (%r)\n' % (filename, msg))
159+ return 1
160+ # Return succes
161+ return 0
162+
163+
164+from tokenize import tokenprog
165+
166+match = {'if':':', 'elif':':', 'while':':', 'return':'\n', \
167+ '(':')', '[':']', '{':'}', '`':'`'}
168+
169+def fixline(line):
170+ # Quick check for easy case
171+ if '=' not in line: return line
172+
173+ i, n = 0, len(line)
174+ stack = []
175+ while i < n:
176+ j = tokenprog.match(line, i)
177+ if j < 0:
178+ # A bad token; forget about the rest of this line
179+ print '(Syntax error:)'
180+ print line,
181+ return line
182+ a, b = tokenprog.regs[3] # Location of the token proper
183+ token = line[a:b]
184+ i = i+j
185+ if stack and token == stack[-1]:
186+ del stack[-1]
187+ elif match.has_key(token):
188+ stack.append(match[token])
189+ elif token == '=' and stack:
190+ line = line[:a] + '==' + line[b:]
191+ i, n = a + len('=='), len(line)
192+ elif token == '==' and not stack:
193+ print '(Warning: \'==\' at top level:)'
194+ print line,
195+ return line
196+
197+if __name__ == "__main__":
198+ main()
sys/src/cmd/python/Demo/scripts/fact.py+49−0
@@ -0,0 +1,49 @@
1+#! /usr/bin/env python
2+
3+# Factorize numbers.
4+# The algorithm is not efficient, but easy to understand.
5+# If there are large factors, it will take forever to find them,
6+# because we try all odd numbers between 3 and sqrt(n)...
7+
8+import sys
9+from math import sqrt
10+
11+error = 'fact.error' # exception
12+
13+def fact(n):
14+ if n < 1: raise error # fact() argument should be >= 1
15+ if n == 1: return [] # special case
16+ res = []
17+ # Treat even factors special, so we can use i = i+2 later
18+ while n%2 == 0:
19+ res.append(2)
20+ n = n/2
21+ # Try odd numbers up to sqrt(n)
22+ limit = sqrt(float(n+1))
23+ i = 3
24+ while i <= limit:
25+ if n%i == 0:
26+ res.append(i)
27+ n = n/i
28+ limit = sqrt(n+1)
29+ else:
30+ i = i+2
31+ if n != 1:
32+ res.append(n)
33+ return res
34+
35+def main():
36+ if len(sys.argv) > 1:
37+ for arg in sys.argv[1:]:
38+ n = eval(arg)
39+ print n, fact(n)
40+ else:
41+ try:
42+ while 1:
43+ n = input()
44+ print n, fact(n)
45+ except EOFError:
46+ pass
47+
48+if __name__ == "__main__":
49+ main()
sys/src/cmd/python/Demo/scripts/find-uname.py+40−0
@@ -0,0 +1,40 @@
1+#!/usr/bin/env python
2+
3+"""
4+For each argument on the command line, look for it in the set of all Unicode
5+names. Arguments are treated as case-insensitive regular expressions, e.g.:
6+
7+ % find-uname 'small letter a$' 'horizontal line'
8+ *** small letter a$ matches ***
9+ LATIN SMALL LETTER A (97)
10+ COMBINING LATIN SMALL LETTER A (867)
11+ CYRILLIC SMALL LETTER A (1072)
12+ PARENTHESIZED LATIN SMALL LETTER A (9372)
13+ CIRCLED LATIN SMALL LETTER A (9424)
14+ FULLWIDTH LATIN SMALL LETTER A (65345)
15+ *** horizontal line matches ***
16+ HORIZONTAL LINE EXTENSION (9135)
17+"""
18+
19+import unicodedata
20+import sys
21+import re
22+
23+def main(args):
24+ unicode_names= []
25+ for ix in range(sys.maxunicode+1):
26+ try:
27+ unicode_names.append( (ix, unicodedata.name(unichr(ix))) )
28+ except ValueError: # no name for the character
29+ pass
30+ for arg in args:
31+ pat = re.compile(arg, re.I)
32+ matches = [(x,y) for (x,y) in unicode_names
33+ if pat.search(y) is not None]
34+ if matches:
35+ print "***", arg, "matches", "***"
36+ for (x,y) in matches:
37+ print "%s (%d)" % (y,x)
38+
39+if __name__ == "__main__":
40+ main(sys.argv[1:])
sys/src/cmd/python/Demo/scripts/from.py+35−0
@@ -0,0 +1,35 @@
1+#! /usr/bin/env python
2+
3+# Print From and Subject of messages in $MAIL.
4+# Extension to multiple mailboxes and other bells & whistles are left
5+# as exercises for the reader.
6+
7+import sys, os
8+
9+# Open mailbox file. Exits with exception when this fails.
10+
11+try:
12+ mailbox = os.environ['MAIL']
13+except (AttributeError, KeyError):
14+ sys.stderr.write('No environment variable $MAIL\n')
15+ sys.exit(2)
16+
17+try:
18+ mail = open(mailbox)
19+except IOError:
20+ sys.exit('Cannot open mailbox file: ' + mailbox)
21+
22+while 1:
23+ line = mail.readline()
24+ if not line:
25+ break # EOF
26+ if line.startswith('From '):
27+ # Start of message found
28+ print line[:-1],
29+ while 1:
30+ line = mail.readline()
31+ if not line or line == '\n':
32+ break
33+ if line.startswith('Subject: '):
34+ print repr(line[9:-1]),
35+ print
sys/src/cmd/python/Demo/scripts/ftpstats.py+145−0
@@ -0,0 +1,145 @@
1+#! /usr/bin/env python
2+
3+# Extract statistics from ftp daemon log.
4+
5+# Usage:
6+# ftpstats [-m maxitems] [-s search] [file]
7+# -m maxitems: restrict number of items in "top-N" lists, default 25.
8+# -s string: restrict statistics to lines containing this string.
9+# Default file is /usr/adm/ftpd; a "-" means read standard input.
10+
11+# The script must be run on the host where the ftp daemon runs.
12+# (At CWI this is currently buizerd.)
13+
14+import os
15+import sys
16+import re
17+import string
18+import getopt
19+
20+pat = '^([a-zA-Z0-9 :]*)!(.*)!(.*)!([<>].*)!([0-9]+)!([0-9]+)$'
21+prog = re.compile(pat)
22+
23+def main():
24+ maxitems = 25
25+ search = None
26+ try:
27+ opts, args = getopt.getopt(sys.argv[1:], 'm:s:')
28+ except getopt.error, msg:
29+ print msg
30+ print 'usage: ftpstats [-m maxitems] [file]'
31+ sys.exit(2)
32+ for o, a in opts:
33+ if o == '-m':
34+ maxitems = string.atoi(a)
35+ if o == '-s':
36+ search = a
37+ file = '/usr/adm/ftpd'
38+ if args: file = args[0]
39+ if file == '-':
40+ f = sys.stdin
41+ else:
42+ try:
43+ f = open(file, 'r')
44+ except IOError, msg:
45+ print file, ':', msg
46+ sys.exit(1)
47+ bydate = {}
48+ bytime = {}
49+ byfile = {}
50+ bydir = {}
51+ byhost = {}
52+ byuser = {}
53+ bytype = {}
54+ lineno = 0
55+ try:
56+ while 1:
57+ line = f.readline()
58+ if not line: break
59+ lineno = lineno + 1
60+ if search and string.find(line, search) < 0:
61+ continue
62+ if prog.match(line) < 0:
63+ print 'Bad line', lineno, ':', repr(line)
64+ continue
65+ items = prog.group(1, 2, 3, 4, 5, 6)
66+ (logtime, loguser, loghost, logfile, logbytes,
67+ logxxx2) = items
68+## print logtime
69+## print '-->', loguser
70+## print '--> -->', loghost
71+## print '--> --> -->', logfile
72+## print '--> --> --> -->', logbytes
73+## print '--> --> --> --> -->', logxxx2
74+## for i in logtime, loghost, logbytes, logxxx2:
75+## if '!' in i: print '???', i
76+ add(bydate, logtime[-4:] + ' ' + logtime[:6], items)
77+ add(bytime, logtime[7:9] + ':00-59', items)
78+ direction, logfile = logfile[0], logfile[1:]
79+ # The real path probably starts at the last //...
80+ while 1:
81+ i = string.find(logfile, '//')
82+ if i < 0: break
83+ logfile = logfile[i+1:]
84+ add(byfile, logfile + ' ' + direction, items)
85+ logdir = os.path.dirname(logfile)
86+## logdir = os.path.normpath(logdir) + '/.'
87+ while 1:
88+ add(bydir, logdir + ' ' + direction, items)
89+ dirhead = os.path.dirname(logdir)
90+ if dirhead == logdir: break
91+ logdir = dirhead
92+ add(byhost, loghost, items)
93+ add(byuser, loguser, items)
94+ add(bytype, direction, items)
95+ except KeyboardInterrupt:
96+ print 'Interrupted at line', lineno
97+ show(bytype, 'by transfer direction', maxitems)
98+ show(bydir, 'by directory', maxitems)
99+ show(byfile, 'by file', maxitems)
100+ show(byhost, 'by host', maxitems)
101+ show(byuser, 'by user', maxitems)
102+ showbar(bydate, 'by date')
103+ showbar(bytime, 'by time of day')
104+
105+def showbar(dict, title):
106+ n = len(title)
107+ print '='*((70-n)/2), title, '='*((71-n)/2)
108+ list = []
109+ keys = dict.keys()
110+ keys.sort()
111+ for key in keys:
112+ n = len(str(key))
113+ list.append((len(dict[key]), key))
114+ maxkeylength = 0
115+ maxcount = 0
116+ for count, key in list:
117+ maxkeylength = max(maxkeylength, len(key))
118+ maxcount = max(maxcount, count)
119+ maxbarlength = 72 - maxkeylength - 7
120+ for count, key in list:
121+ barlength = int(round(maxbarlength*float(count)/maxcount))
122+ bar = '*'*barlength
123+ print '%5d %-*s %s' % (count, maxkeylength, key, bar)
124+
125+def show(dict, title, maxitems):
126+ if len(dict) > maxitems:
127+ title = title + ' (first %d)'%maxitems
128+ n = len(title)
129+ print '='*((70-n)/2), title, '='*((71-n)/2)
130+ list = []
131+ keys = dict.keys()
132+ for key in keys:
133+ list.append((-len(dict[key]), key))
134+ list.sort()
135+ for count, key in list[:maxitems]:
136+ print '%5d %s' % (-count, key)
137+
138+def add(dict, key, item):
139+ if dict.has_key(key):
140+ dict[key].append(item)
141+ else:
142+ dict[key] = [item]
143+
144+if __name__ == "__main__":
145+ main()
sys/src/cmd/python/Demo/scripts/lpwatch.py+110−0
@@ -0,0 +1,110 @@
1+#! /usr/bin/env python
2+
3+# Watch line printer queue(s).
4+# Intended for BSD 4.3 lpq.
5+
6+import posix
7+import sys
8+import time
9+import string
10+
11+DEF_PRINTER = 'psc'
12+DEF_DELAY = 10
13+
14+def main():
15+ delay = DEF_DELAY # XXX Use getopt() later
16+ try:
17+ thisuser = posix.environ['LOGNAME']
18+ except:
19+ thisuser = posix.environ['USER']
20+ printers = sys.argv[1:]
21+ if printers:
22+ # Strip '-P' from printer names just in case
23+ # the user specified it...
24+ for i in range(len(printers)):
25+ if printers[i][:2] == '-P':
26+ printers[i] = printers[i][2:]
27+ else:
28+ if posix.environ.has_key('PRINTER'):
29+ printers = [posix.environ['PRINTER']]
30+ else:
31+ printers = [DEF_PRINTER]
32+ #
33+ clearhome = posix.popen('clear', 'r').read()
34+ #
35+ while 1:
36+ text = clearhome
37+ for name in printers:
38+ text = text + makestatus(name, thisuser) + '\n'
39+ print text
40+ time.sleep(delay)
41+
42+def makestatus(name, thisuser):
43+ pipe = posix.popen('lpq -P' + name + ' 2>&1', 'r')
44+ lines = []
45+ users = {}
46+ aheadbytes = 0
47+ aheadjobs = 0
48+ userseen = 0
49+ totalbytes = 0
50+ totaljobs = 0
51+ while 1:
52+ line = pipe.readline()
53+ if not line: break
54+ fields = string.split(line)
55+ n = len(fields)
56+ if len(fields) >= 6 and fields[n-1] == 'bytes':
57+ rank = fields[0]
58+ user = fields[1]
59+ job = fields[2]
60+ files = fields[3:-2]
61+ bytes = eval(fields[n-2])
62+ if user == thisuser:
63+ userseen = 1
64+ elif not userseen:
65+ aheadbytes = aheadbytes + bytes
66+ aheadjobs = aheadjobs + 1
67+ totalbytes = totalbytes + bytes
68+ totaljobs = totaljobs + 1
69+ if users.has_key(user):
70+ ujobs, ubytes = users[user]
71+ else:
72+ ujobs, ubytes = 0, 0
73+ ujobs = ujobs + 1
74+ ubytes = ubytes + bytes
75+ users[user] = ujobs, ubytes
76+ else:
77+ if fields and fields[0] <> 'Rank':
78+ line = string.strip(line)
79+ if line == 'no entries':
80+ line = name + ': idle'
81+ elif line[-22:] == ' is ready and printing':
82+ line = name
83+ lines.append(line)
84+ #
85+ if totaljobs:
86+ line = '%d K' % ((totalbytes+1023)/1024)
87+ if totaljobs <> len(users):
88+ line = line + ' (%d jobs)' % totaljobs
89+ if len(users) == 1:
90+ line = line + ' for %s' % (users.keys()[0],)
91+ else:
92+ line = line + ' for %d users' % len(users)
93+ if userseen:
94+ if aheadjobs == 0:
95+ line = line + ' (%s first)' % thisuser
96+ else:
97+ line = line + ' (%d K before %s)' % (
98+ (aheadbytes+1023)/1024, thisuser)
99+ lines.append(line)
100+ #
101+ sts = pipe.close()
102+ if sts:
103+ lines.append('lpq exit status %r' % (sts,))
104+ return string.joinfields(lines, ': ')
105+
106+if __name__ == "__main__":
107+ try:
108+ main()
109+ except KeyboardInterrupt:
110+ pass
sys/src/cmd/python/Demo/scripts/makedir.py+21−0
@@ -0,0 +1,21 @@
1+#! /usr/bin/env python
2+
3+# Like mkdir, but also make intermediate directories if necessary.
4+# It is not an error if the given directory already exists (as long
5+# as it is a directory).
6+# Errors are not treated specially -- you just get a Python exception.
7+
8+import sys, os
9+
10+def main():
11+ for p in sys.argv[1:]:
12+ makedirs(p)
13+
14+def makedirs(p):
15+ if p and not os.path.isdir(p):
16+ head, tail = os.path.split(p)
17+ makedirs(head)
18+ os.mkdir(p, 0777)
19+
20+if __name__ == "__main__":
21+ main()
sys/src/cmd/python/Demo/scripts/markov.py+117−0
@@ -0,0 +1,117 @@
1+#! /usr/bin/env python
2+
3+class Markov:
4+ def __init__(self, histsize, choice):
5+ self.histsize = histsize
6+ self.choice = choice
7+ self.trans = {}
8+ def add(self, state, next):
9+ if not self.trans.has_key(state):
10+ self.trans[state] = [next]
11+ else:
12+ self.trans[state].append(next)
13+ def put(self, seq):
14+ n = self.histsize
15+ add = self.add
16+ add(None, seq[:0])
17+ for i in range(len(seq)):
18+ add(seq[max(0, i-n):i], seq[i:i+1])
19+ add(seq[len(seq)-n:], None)
20+ def get(self):
21+ choice = self.choice
22+ trans = self.trans
23+ n = self.histsize
24+ seq = choice(trans[None])
25+ while 1:
26+ subseq = seq[max(0, len(seq)-n):]
27+ options = trans[subseq]
28+ next = choice(options)
29+ if not next: break
30+ seq = seq + next
31+ return seq
32+
33+def test():
34+ import sys, string, random, getopt
35+ args = sys.argv[1:]
36+ try:
37+ opts, args = getopt.getopt(args, '0123456789cdw')
38+ except getopt.error:
39+ print 'Usage: markov [-#] [-cddqw] [file] ...'
40+ print 'Options:'
41+ print '-#: 1-digit history size (default 2)'
42+ print '-c: characters (default)'
43+ print '-w: words'
44+ print '-d: more debugging output'
45+ print '-q: no debugging output'
46+ print 'Input files (default stdin) are split in paragraphs'
47+ print 'separated blank lines and each paragraph is split'
48+ print 'in words by whitespace, then reconcatenated with'
49+ print 'exactly one space separating words.'
50+ print 'Output consists of paragraphs separated by blank'
51+ print 'lines, where lines are no longer than 72 characters.'
52+ histsize = 2
53+ do_words = 0
54+ debug = 1
55+ for o, a in opts:
56+ if '-0' <= o <= '-9': histsize = eval(o[1:])
57+ if o == '-c': do_words = 0
58+ if o == '-d': debug = debug + 1
59+ if o == '-q': debug = 0
60+ if o == '-w': do_words = 1
61+ if not args: args = ['-']
62+ m = Markov(histsize, random.choice)
63+ try:
64+ for filename in args:
65+ if filename == '-':
66+ f = sys.stdin
67+ if f.isatty():
68+ print 'Sorry, need stdin from file'
69+ continue
70+ else:
71+ f = open(filename, 'r')
72+ if debug: print 'processing', filename, '...'
73+ text = f.read()
74+ f.close()
75+ paralist = string.splitfields(text, '\n\n')
76+ for para in paralist:
77+ if debug > 1: print 'feeding ...'
78+ words = string.split(para)
79+ if words:
80+ if do_words: data = tuple(words)
81+ else: data = string.joinfields(words, ' ')
82+ m.put(data)
83+ except KeyboardInterrupt:
84+ print 'Interrupted -- continue with data read so far'
85+ if not m.trans:
86+ print 'No valid input files'
87+ return
88+ if debug: print 'done.'
89+ if debug > 1:
90+ for key in m.trans.keys():
91+ if key is None or len(key) < histsize:
92+ print repr(key), m.trans[key]
93+ if histsize == 0: print repr(''), m.trans['']
94+ print
95+ while 1:
96+ data = m.get()
97+ if do_words: words = data
98+ else: words = string.split(data)
99+ n = 0
100+ limit = 72
101+ for w in words:
102+ if n + len(w) > limit:
103+ print
104+ n = 0
105+ print w,
106+ n = n + len(w) + 1
107+ print
108+ print
109+
110+def tuple(list):
111+ if len(list) == 0: return ()
112+ if len(list) == 1: return (list[0],)
113+ i = len(list)/2
114+ return tuple(list[:i]) + tuple(list[i:])
115+
116+if __name__ == "__main__":
117+ test()
sys/src/cmd/python/Demo/scripts/mboxconvert.py+124−0
@@ -0,0 +1,124 @@
1+#! /usr/bin/env python
2+
3+# Convert MH directories (1 message per file) or MMDF mailboxes (4x^A
4+# delimited) to unix mailbox (From ... delimited) on stdout.
5+# If -f is given, files contain one message per file (e.g. MH messages)
6+
7+import rfc822
8+import sys
9+import time
10+import os
11+import stat
12+import getopt
13+import re
14+
15+def main():
16+ dofile = mmdf
17+ try:
18+ opts, args = getopt.getopt(sys.argv[1:], 'f')
19+ except getopt.error, msg:
20+ sys.stderr.write('%s\n' % msg)
21+ sys.exit(2)
22+ for o, a in opts:
23+ if o == '-f':
24+ dofile = message
25+ if not args:
26+ args = ['-']
27+ sts = 0
28+ for arg in args:
29+ if arg == '-' or arg == '':
30+ sts = dofile(sys.stdin) or sts
31+ elif os.path.isdir(arg):
32+ sts = mh(arg) or sts
33+ elif os.path.isfile(arg):
34+ try:
35+ f = open(arg)
36+ except IOError, msg:
37+ sys.stderr.write('%s: %s\n' % (arg, msg))
38+ sts = 1
39+ continue
40+ sts = dofile(f) or sts
41+ f.close()
42+ else:
43+ sys.stderr.write('%s: not found\n' % arg)
44+ sts = 1
45+ if sts:
46+ sys.exit(sts)
47+
48+numeric = re.compile('[1-9][0-9]*')
49+
50+def mh(dir):
51+ sts = 0
52+ msgs = os.listdir(dir)
53+ for msg in msgs:
54+ if numeric.match(msg) != len(msg):
55+ continue
56+ fn = os.path.join(dir, msg)
57+ try:
58+ f = open(fn)
59+ except IOError, msg:
60+ sys.stderr.write('%s: %s\n' % (fn, msg))
61+ sts = 1
62+ continue
63+ sts = message(f) or sts
64+ return sts
65+
66+def mmdf(f):
67+ sts = 0
68+ while 1:
69+ line = f.readline()
70+ if not line:
71+ break
72+ if line == '\1\1\1\1\n':
73+ sts = message(f, line) or sts
74+ else:
75+ sys.stderr.write(
76+ 'Bad line in MMFD mailbox: %r\n' % (line,))
77+ return sts
78+
79+counter = 0 # for generating unique Message-ID headers
80+
81+def message(f, delimiter = ''):
82+ sts = 0
83+ # Parse RFC822 header
84+ m = rfc822.Message(f)
85+ # Write unix header line
86+ fullname, email = m.getaddr('From')
87+ tt = m.getdate('Date')
88+ if tt:
89+ t = time.mktime(tt)
90+ else:
91+ sys.stderr.write(
92+ 'Unparseable date: %r\n' % (m.getheader('Date'),))
93+ t = os.fstat(f.fileno())[stat.ST_MTIME]
94+ print 'From', email, time.ctime(t)
95+ # Copy RFC822 header
96+ for line in m.headers:
97+ print line,
98+ # Invent Message-ID header if none is present
99+ if not m.has_key('message-id'):
100+ global counter
101+ counter = counter + 1
102+ msgid = "<%s.%d>" % (hex(t), counter)
103+ sys.stderr.write("Adding Message-ID %s (From %s)\n" %
104+ (msgid, email))
105+ print "Message-ID:", msgid
106+ print
107+ # Copy body
108+ while 1:
109+ line = f.readline()
110+ if line == delimiter:
111+ break
112+ if not line:
113+ sys.stderr.write('Unexpected EOF in message\n')
114+ sts = 1
115+ break
116+ if line[:5] == 'From ':
117+ line = '>' + line
118+ print line,
119+ # Print trailing newline
120+ print
121+ return sts
122+
123+if __name__ == "__main__":
124+ main()
sys/src/cmd/python/Demo/scripts/mkrcs.py+61−0
@@ -0,0 +1,61 @@
1+#! /usr/bin/env python
2+
3+# A rather specialized script to make sure that a symbolic link named
4+# RCS exists pointing to a real RCS directory in a parallel tree
5+# referenced as RCStree in an ancestor directory.
6+# (I use this because I like my RCS files to reside on a physically
7+# different machine).
8+
9+import os
10+
11+def main():
12+ rcstree = 'RCStree'
13+ rcs = 'RCS'
14+ if os.path.islink(rcs):
15+ print '%r is a symlink to %r' % (rcs, os.readlink(rcs))
16+ return
17+ if os.path.isdir(rcs):
18+ print '%r is an ordinary directory' % (rcs,)
19+ return
20+ if os.path.exists(rcs):
21+ print '%r is a file?!?!' % (rcs,)
22+ return
23+ #
24+ p = os.getcwd()
25+ up = ''
26+ down = ''
27+ # Invariants:
28+ # (1) join(p, down) is the current directory
29+ # (2) up is the same directory as p
30+ # Ergo:
31+ # (3) join(up, down) is the current directory
32+ #print 'p =', repr(p)
33+ while not os.path.isdir(os.path.join(p, rcstree)):
34+ head, tail = os.path.split(p)
35+ #print 'head = %r; tail = %r' % (head, tail)
36+ if not tail:
37+ print 'Sorry, no ancestor dir contains %r' % (rcstree,)
38+ return
39+ p = head
40+ up = os.path.join(os.pardir, up)
41+ down = os.path.join(tail, down)
42+ #print 'p = %r; up = %r; down = %r' % (p, up, down)
43+ there = os.path.join(up, rcstree)
44+ there = os.path.join(there, down)
45+ there = os.path.join(there, rcs)
46+ if os.path.isdir(there):
47+ print '%r already exists' % (there, )
48+ else:
49+ print 'making %r' % (there,)
50+ makedirs(there)
51+ print 'making symlink %r -> %r' % (rcs, there)
52+ os.symlink(there, rcs)
53+
54+def makedirs(p):
55+ if not os.path.isdir(p):
56+ head, tail = os.path.split(p)
57+ makedirs(head)
58+ os.mkdir(p, 0777)
59+
60+if __name__ == "__main__":
61+ main()
sys/src/cmd/python/Demo/scripts/morse.py+149−0
@@ -0,0 +1,149 @@
1+# DAH should be three DOTs.
2+# Space between DOTs and DAHs should be one DOT.
3+# Space between two letters should be one DAH.
4+# Space between two words should be DOT DAH DAH.
5+
6+import sys, math, audiodev
7+
8+DOT = 30
9+DAH = 3 * DOT
10+OCTAVE = 2 # 1 == 441 Hz, 2 == 882 Hz, ...
11+
12+morsetab = {
13+ 'A': '.-', 'a': '.-',
14+ 'B': '-...', 'b': '-...',
15+ 'C': '-.-.', 'c': '-.-.',
16+ 'D': '-..', 'd': '-..',
17+ 'E': '.', 'e': '.',
18+ 'F': '..-.', 'f': '..-.',
19+ 'G': '--.', 'g': '--.',
20+ 'H': '....', 'h': '....',
21+ 'I': '..', 'i': '..',
22+ 'J': '.---', 'j': '.---',
23+ 'K': '-.-', 'k': '-.-',
24+ 'L': '.-..', 'l': '.-..',
25+ 'M': '--', 'm': '--',
26+ 'N': '-.', 'n': '-.',
27+ 'O': '---', 'o': '---',
28+ 'P': '.--.', 'p': '.--.',
29+ 'Q': '--.-', 'q': '--.-',
30+ 'R': '.-.', 'r': '.-.',
31+ 'S': '...', 's': '...',
32+ 'T': '-', 't': '-',
33+ 'U': '..-', 'u': '..-',
34+ 'V': '...-', 'v': '...-',
35+ 'W': '.--', 'w': '.--',
36+ 'X': '-..-', 'x': '-..-',
37+ 'Y': '-.--', 'y': '-.--',
38+ 'Z': '--..', 'z': '--..',
39+ '0': '-----',
40+ '1': '.----',
41+ '2': '..---',
42+ '3': '...--',
43+ '4': '....-',
44+ '5': '.....',
45+ '6': '-....',
46+ '7': '--...',
47+ '8': '---..',
48+ '9': '----.',
49+ ',': '--..--',
50+ '.': '.-.-.-',
51+ '?': '..--..',
52+ ';': '-.-.-.',
53+ ':': '---...',
54+ "'": '.----.',
55+ '-': '-....-',
56+ '/': '-..-.',
57+ '(': '-.--.-',
58+ ')': '-.--.-',
59+ '_': '..--.-',
60+ ' ': ' '
61+}
62+
63+# If we play at 44.1 kHz (which we do), then if we produce one sine
64+# wave in 100 samples, we get a tone of 441 Hz. If we produce two
65+# sine waves in these 100 samples, we get a tone of 882 Hz. 882 Hz
66+# appears to be a nice one for playing morse code.
67+def mkwave(octave):
68+ global sinewave, nowave
69+ sinewave = ''
70+ for i in range(100):
71+ val = int(math.sin(math.pi * float(i) * octave / 50.0) * 30000)
72+ sinewave = sinewave + chr((val >> 8) & 255) + chr(val & 255)
73+ nowave = '\0' * 200
74+
75+mkwave(OCTAVE)
76+
77+def main():
78+ import getopt, string
79+ try:
80+ opts, args = getopt.getopt(sys.argv[1:], 'o:p:')
81+ except getopt.error:
82+ sys.stderr.write('Usage ' + sys.argv[0] +
83+ ' [ -o outfile ] [ args ] ...\n')
84+ sys.exit(1)
85+ dev = None
86+ for o, a in opts:
87+ if o == '-o':
88+ import aifc
89+ dev = aifc.open(a, 'w')
90+ dev.setframerate(44100)
91+ dev.setsampwidth(2)
92+ dev.setnchannels(1)
93+ if o == '-p':
94+ mkwave(string.atoi(a))
95+ if not dev:
96+ import audiodev
97+ dev = audiodev.AudioDev()
98+ dev.setoutrate(44100)
99+ dev.setsampwidth(2)
100+ dev.setnchannels(1)
101+ dev.close = dev.stop
102+ dev.writeframesraw = dev.writeframes
103+ if args:
104+ line = string.join(args)
105+ else:
106+ line = sys.stdin.readline()
107+ while line:
108+ mline = morse(line)
109+ play(mline, dev)
110+ if hasattr(dev, 'wait'):
111+ dev.wait()
112+ if not args:
113+ line = sys.stdin.readline()
114+ else:
115+ line = ''
116+ dev.close()
117+
118+# Convert a string to morse code with \001 between the characters in
119+# the string.
120+def morse(line):
121+ res = ''
122+ for c in line:
123+ try:
124+ res = res + morsetab[c] + '\001'
125+ except KeyError:
126+ pass
127+ return res
128+
129+# Play a line of morse code.
130+def play(line, dev):
131+ for c in line:
132+ if c == '.':
133+ sine(dev, DOT)
134+ elif c == '-':
135+ sine(dev, DAH)
136+ else: # space
137+ pause(dev, DAH + DOT)
138+ pause(dev, DOT)
139+
140+def sine(dev, length):
141+ for i in range(length):
142+ dev.writeframesraw(sinewave)
143+
144+def pause(dev, length):
145+ for i in range(length):
146+ dev.writeframesraw(nowave)
147+
148+if __name__ == '__main__' or sys.argv[0] == __name__:
149+ main()
sys/src/cmd/python/Demo/scripts/newslist.doc+59−0
@@ -0,0 +1,59 @@
1+ NEWSLIST
2+ ========
3+ A program to assist HTTP browsing of newsgroups
4+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5+
6+WWW browsers such as NCSA Mosaic allow the user to read newsgroup
7+articles by specifying the group name in a URL eg 'news:comp.answers'.
8+
9+To browse through many groups, though, (and there are several thousand
10+of them) you really need a page or pages containing links to all the
11+groups. There are some good ones out there, for example,
12+
13+ http://info.cern.ch/hypertext/DataSources/News/Groups/Overview.html
14+
15+is the standard one at CERN, but it only shows the groups available there,
16+which may be rather different from those available on your machine.
17+
18+Newslist is a program which creates a hierarchy of pages for you based
19+on the groups available from YOUR server. It is written in python - a
20+splendid interpreted object-oriented language which I suggest you get
21+right now from the directory /pub/python at ftp.cwi.nl, if you haven't
22+already got it.
23+
24+You should be able to see some sample output by looking at:
25+ http://pelican.cl.cam.ac.uk/newspage/root.html
26+
27+Descriptions of newsgroups can be added from a file with one group
28+per line. eg:
29+
30+ alt.foo Articles about foo
31+ comp.bar Programming in 'bar' and related languages
32+
33+A suitable list detailing most groups can be found at ftp.uu.net in
34+/uunet-info/newsgroups.gz.
35+
36+Make sure you read the information at the beginning of the program source and
37+configure the variables before running.
38+
39+In addition to python, you need:
40+
41+ An NNTP-based news feed.
42+ A directory in which to put the pages.
43+
44+The programming is not very beautiful, but it works! It comes with no
45+warranty, express or implied, but with the hope that some others may
46+find it useful.
47+
48+Comments, improvements & suggestions welcomed.
49+Quentin Stafford-Fraser
50+
51+ ----------------------------------------------------------------------
52+ Quentin Stafford-Fraser
53+ http://pelican.cl.cam.ac.uk/people/qs101/me.html
54+
55+ Cambridge University Computer Lab Rank Xerox Cambridge EuroPARC
56+ qs101@cl.cam.ac.uk fraser@europarc.xerox.com
57+ Tel: +44 223 334411 Tel: +44 223 341521
58+ Fax: +44 223 334679 Fax: +44 223 341510
59+ ----------------------------------------------------------------------
sys/src/cmd/python/Demo/scripts/newslist.py+366−0
@@ -0,0 +1,366 @@
1+#! /usr/bin/env python
2+#######################################################################
3+# Newslist $Revision: 37320 $
4+#
5+# Syntax:
6+# newslist [ -a ]
7+#
8+# This is a program to create a directory full of HTML pages
9+# which between them contain links to all the newsgroups available
10+# on your server.
11+#
12+# The -a option causes a complete list of all groups to be read from
13+# the server rather than just the ones which have appeared since last
14+# execution. This recreates the local list from scratch. Use this on
15+# the first invocation of the program, and from time to time thereafter.
16+# When new groups are first created they may appear on your server as
17+# empty groups. By default, empty groups are ignored by the -a option.
18+# However, these new groups will not be created again, and so will not
19+# appear in the server's list of 'new groups' at a later date. Hence it
20+# won't appear until you do a '-a' after some articles have appeared.
21+#
22+# I should really keep a list of ignored empty groups and re-check them
23+# for articles on every run, but I haven't got around to it yet.
24+#
25+# This assumes an NNTP news feed.
26+#
27+# Feel free to copy, distribute and modify this code for
28+# non-commercial use. If you make any useful modifications, let me
29+# know!
30+#
31+# (c) Quentin Stafford-Fraser 1994
32+# fraser@europarc.xerox.com qs101@cl.cam.ac.uk
33+# #
34+#######################################################################
35+import sys,nntplib, string, marshal, time, os, posix, string
36+
37+#######################################################################
38+# Check these variables before running! #
39+
40+# Top directory.
41+# Filenames which don't start with / are taken as being relative to this.
42+topdir='/anfs/qsbigdisc/web/html/newspage'
43+
44+# The name of your NNTP host
45+# eg.
46+# newshost = 'nntp-serv.cl.cam.ac.uk'
47+# or use following to get the name from the NNTPSERVER environment
48+# variable:
49+# newshost = posix.environ['NNTPSERVER']
50+newshost = 'nntp-serv.cl.cam.ac.uk'
51+
52+# The filename for a local cache of the newsgroup list
53+treefile = 'grouptree'
54+
55+# The filename for descriptions of newsgroups
56+# I found a suitable one at ftp.uu.net in /uunet-info/newgroups.gz
57+# You can set this to '' if you don't wish to use one.
58+descfile = 'newsgroups'
59+
60+# The directory in which HTML pages should be created
61+# eg.
62+# pagedir = '/usr/local/lib/html/newspage'
63+# pagedir = 'pages'
64+pagedir = topdir
65+
66+# The html prefix which will refer to this directory
67+# eg.
68+# httppref = '/newspage/',
69+# or leave blank for relative links between pages: (Recommended)
70+# httppref = ''
71+httppref = ''
72+
73+# The name of the 'root' news page in this directory.
74+# A .html suffix will be added.
75+rootpage = 'root'
76+
77+# Set skipempty to 0 if you wish to see links to empty groups as well.
78+# Only affects the -a option.
79+skipempty = 1
80+
81+# pagelinkicon can contain html to put an icon after links to
82+# further pages. This helps to make important links stand out.
83+# Set to '' if not wanted, or '...' is quite a good one.
84+pagelinkicon='... <img src="http://pelican.cl.cam.ac.uk/icons/page.xbm"> '
85+
86+# ---------------------------------------------------------------------
87+# Less important personal preferences:
88+
89+# Sublistsize controls the maximum number of items the will appear as
90+# an indented sub-list before the whole thing is moved onto a different
91+# page. The smaller this is, the more pages you will have, but the
92+# shorter each will be.
93+sublistsize = 4
94+
95+# That should be all. #
96+#######################################################################
97+
98+for dir in os.curdir, os.environ['HOME']:
99+ rcfile = os.path.join(dir, '.newslistrc.py')
100+ if os.path.exists(rcfile):
101+ print rcfile
102+ execfile(rcfile)
103+ break
104+
105+from nntplib import NNTP
106+from stat import *
107+
108+rcsrev = '$Revision: 37320 $'
109+rcsrev = string.join(filter(lambda s: '$' not in s, string.split(rcsrev)))
110+desc = {}
111+
112+# Make (possibly) relative filenames into absolute ones
113+treefile = os.path.join(topdir,treefile)
114+descfile = os.path.join(topdir,descfile)
115+page = os.path.join(topdir,pagedir)
116+
117+# First the bits for creating trees ---------------------------
118+
119+# Addtotree creates/augments a tree from a list of group names
120+def addtotree(tree, groups):
121+ print 'Updating tree...'
122+ for i in groups:
123+ parts = string.splitfields(i,'.')
124+ makeleaf(tree, parts)
125+
126+# Makeleaf makes a leaf and the branch leading to it if necessary
127+def makeleaf(tree,path):
128+ j = path[0]
129+ l = len(path)
130+
131+ if not tree.has_key(j):
132+ tree[j] = {}
133+ if l == 1:
134+ tree[j]['.'] = '.'
135+ if l > 1:
136+ makeleaf(tree[j],path[1:])
137+
138+# Then the bits for outputting trees as pages ----------------
139+
140+# Createpage creates an HTML file named <root>.html containing links
141+# to those groups beginning with <root>.
142+
143+def createpage(root, tree, p):
144+ filename = os.path.join(pagedir,root+'.html')
145+ if root == rootpage:
146+ detail = ''
147+ else:
148+ detail = ' under ' + root
149+ f = open(filename,'w')
150+ # f.write('Content-Type: text/html\n')
151+ f.write('<TITLE>Newsgroups available' + detail + '</TITLE>\n')
152+ f.write('<H1>Newsgroups available' + detail +'</H1>\n')
153+ f.write('<A HREF="'+httppref+rootpage+'.html">Back to top level</A><P>\n')
154+ printtree(f,tree,0,p)
155+ f.write('<I>This page automatically created by \'newslist\' v. '+rcsrev+'.')
156+ f.write(time.ctime(time.time()) + '</I><P>')
157+ f.close()
158+
159+# Printtree prints the groups as a bulleted list. Groups with
160+# more than <sublistsize> subgroups will be put on a separate page.
161+# Other sets of subgroups are just indented.
162+
163+def printtree(f, tree, indent, p):
164+ global desc
165+ l = len(tree)
166+
167+ if l > sublistsize and indent>0:
168+ # Create a new page and a link to it
169+ f.write('<LI><B><A HREF="'+httppref+p[1:]+'.html">')
170+ f.write(p[1:]+'.*')
171+ f.write('</A></B>'+pagelinkicon+'\n')
172+ createpage(p[1:], tree, p)
173+ return
174+
175+ kl = tree.keys()
176+
177+ if l > 1:
178+ kl.sort()
179+ if indent > 0:
180+ # Create a sub-list
181+ f.write('<LI>'+p[1:]+'\n<UL>')
182+ else:
183+ # Create a main list
184+ f.write('<UL>')
185+ indent = indent + 1
186+
187+ for i in kl:
188+ if i == '.':
189+ # Output a newsgroup
190+ f.write('<LI><A HREF="news:' + p[1:] + '">'+ p[1:] + '</A> ')
191+ if desc.has_key(p[1:]):
192+ f.write(' <I>'+desc[p[1:]]+'</I>\n')
193+ else:
194+ f.write('\n')
195+ else:
196+ # Output a hierarchy
197+ printtree(f,tree[i], indent, p+'.'+i)
198+
199+ if l > 1:
200+ f.write('\n</UL>')
201+
202+# Reading descriptions file ---------------------------------------
203+
204+# This returns an array mapping group name to its description
205+
206+def readdesc(descfile):
207+ global desc
208+
209+ desc = {}
210+
211+ if descfile == '':
212+ return
213+
214+ try:
215+ d = open(descfile, 'r')
216+ print 'Reading descriptions...'
217+ except (IOError):
218+ print 'Failed to open description file ' + descfile
219+ return
220+ l = d.readline()
221+ while l != '':
222+ bits = string.split(l)
223+ try:
224+ grp = bits[0]
225+ dsc = string.join(bits[1:])
226+ if len(dsc)>1:
227+ desc[grp] = dsc
228+ except (IndexError):
229+ pass
230+ l = d.readline()
231+
232+# Check that ouput directory exists, ------------------------------
233+# and offer to create it if not
234+
235+def checkopdir(pagedir):
236+ if not os.path.isdir(pagedir):
237+ print 'Directory '+pagedir+' does not exist.'
238+ print 'Shall I create it for you? (y/n)'
239+ if sys.stdin.readline()[0] == 'y':
240+ try:
241+ os.mkdir(pagedir,0777)
242+ except:
243+ print 'Sorry - failed!'
244+ sys.exit(1)
245+ else:
246+ print 'OK. Exiting.'
247+ sys.exit(1)
248+
249+# Read and write current local tree ----------------------------------
250+
251+def readlocallist(treefile):
252+ print 'Reading current local group list...'
253+ tree = {}
254+ try:
255+ treetime = time.localtime(os.stat(treefile)[ST_MTIME])
256+ except:
257+ print '\n*** Failed to open local group cache '+treefile
258+ print 'If this is the first time you have run newslist, then'
259+ print 'use the -a option to create it.'
260+ sys.exit(1)
261+ treedate = '%02d%02d%02d' % (treetime[0] % 100 ,treetime[1], treetime[2])
262+ try:
263+ dump = open(treefile,'r')
264+ tree = marshal.load(dump)
265+ dump.close()
266+ except (IOError):
267+ print 'Cannot open local group list ' + treefile
268+ return (tree, treedate)
269+
270+def writelocallist(treefile, tree):
271+ try:
272+ dump = open(treefile,'w')
273+ groups = marshal.dump(tree,dump)
274+ dump.close()
275+ print 'Saved list to '+treefile+'\n'
276+ except:
277+ print 'Sorry - failed to write to local group cache '+treefile
278+ print 'Does it (or its directory) have the correct permissions?'
279+ sys.exit(1)
280+
281+# Return list of all groups on server -----------------------------
282+
283+def getallgroups(server):
284+ print 'Getting list of all groups...'
285+ treedate='010101'
286+ info = server.list()[1]
287+ groups = []
288+ print 'Processing...'
289+ if skipempty:
290+ print '\nIgnoring following empty groups:'
291+ for i in info:
292+ grpname = string.split(i[0])[0]
293+ if skipempty and string.atoi(i[1]) < string.atoi(i[2]):
294+ print grpname+' ',
295+ else:
296+ groups.append(grpname)
297+ print '\n'
298+ if skipempty:
299+ print '(End of empty groups)'
300+ return groups
301+
302+# Return list of new groups on server -----------------------------
303+
304+def getnewgroups(server, treedate):
305+ print 'Getting list of new groups since start of '+treedate+'...',
306+ info = server.newgroups(treedate,'000001')[1]
307+ print 'got %d.' % len(info)
308+ print 'Processing...',
309+ groups = []
310+ for i in info:
311+ grpname = string.split(i)[0]
312+ groups.append(grpname)
313+ print 'Done'
314+ return groups
315+
316+# Now the main program --------------------------------------------
317+
318+def main():
319+ global desc
320+
321+ tree={}
322+
323+ # Check that the output directory exists
324+ checkopdir(pagedir);
325+
326+ try:
327+ print 'Connecting to '+newshost+'...'
328+ if sys.version[0] == '0':
329+ s = NNTP.init(newshost)
330+ else:
331+ s = NNTP(newshost)
332+ connected = 1
333+ except (nntplib.error_temp, nntplib.error_perm), x:
334+ print 'Error connecting to host:', x
335+ print 'I\'ll try to use just the local list.'
336+ connected = 0
337+
338+ # If -a is specified, read the full list of groups from server
339+ if connected and len(sys.argv) > 1 and sys.argv[1] == '-a':
340+
341+ groups = getallgroups(s)
342+
343+ # Otherwise just read the local file and then add
344+ # groups created since local file last modified.
345+ else:
346+
347+ (tree, treedate) = readlocallist(treefile)
348+ if connected:
349+ groups = getnewgroups(s, treedate)
350+
351+ if connected:
352+ addtotree(tree, groups)
353+ writelocallist(treefile,tree)
354+
355+ # Read group descriptions
356+ readdesc(descfile)
357+
358+ print 'Creating pages...'
359+ createpage(rootpage, tree, '')
360+ print 'Done'
361+
362+if __name__ == "__main__":
363+ main()
364+
365+# That's all folks
366+######################################################################
sys/src/cmd/python/Demo/scripts/pi.py+34−0
@@ -0,0 +1,34 @@
1+#! /usr/bin/env python
2+
3+# Print digits of pi forever.
4+#
5+# The algorithm, using Python's 'long' integers ("bignums"), works
6+# with continued fractions, and was conceived by Lambert Meertens.
7+#
8+# See also the ABC Programmer's Handbook, by Geurts, Meertens & Pemberton,
9+# published by Prentice-Hall (UK) Ltd., 1990.
10+
11+import sys
12+
13+def main():
14+ k, a, b, a1, b1 = 2L, 4L, 1L, 12L, 4L
15+ while 1:
16+ # Next approximation
17+ p, q, k = k*k, 2L*k+1L, k+1L
18+ a, b, a1, b1 = a1, b1, p*a+q*a1, p*b+q*b1
19+ # Print common digits
20+ d, d1 = a/b, a1/b1
21+ while d == d1:
22+ output(d)
23+ a, a1 = 10L*(a%b), 10L*(a1%b1)
24+ d, d1 = a/b, a1/b1
25+
26+def output(d):
27+ # Use write() to avoid spaces between the digits
28+ # Use str() to avoid the 'L'
29+ sys.stdout.write(str(d))
30+ # Flush so the output is seen immediately
31+ sys.stdout.flush()
32+
33+if __name__ == "__main__":
34+ main()
sys/src/cmd/python/Demo/scripts/pp.py+130−0
@@ -0,0 +1,130 @@
1+#! /usr/bin/env python
2+
3+# Emulate some Perl command line options.
4+# Usage: pp [-a] [-c] [-d] [-e scriptline] [-F fieldsep] [-n] [-p] [file] ...
5+# Where the options mean the following:
6+# -a : together with -n or -p, splits each line into list F
7+# -c : check syntax only, do not execute any code
8+# -d : run the script under the debugger, pdb
9+# -e scriptline : gives one line of the Python script; may be repeated
10+# -F fieldsep : sets the field separator for the -a option [not in Perl]
11+# -n : runs the script for each line of input
12+# -p : prints the line after the script has run
13+# When no script lines have been passed, the first file argument
14+# contains the script. With -n or -p, the remaining arguments are
15+# read as input to the script, line by line. If a file is '-'
16+# or missing, standard input is read.
17+
18+# XXX To do:
19+# - add -i extension option (change files in place)
20+# - make a single loop over the files and lines (changes effect of 'break')?
21+# - add an option to specify the record separator
22+# - except for -n/-p, run directly from the file if at all possible
23+
24+import sys
25+import string
26+import getopt
27+
28+FS = ''
29+SCRIPT = []
30+AFLAG = 0
31+CFLAG = 0
32+DFLAG = 0
33+NFLAG = 0
34+PFLAG = 0
35+
36+try:
37+ optlist, ARGS = getopt.getopt(sys.argv[1:], 'acde:F:np')
38+except getopt.error, msg:
39+ sys.stderr.write(sys.argv[0] + ': ' + msg + '\n')
40+ sys.exit(2)
41+
42+for option, optarg in optlist:
43+ if option == '-a':
44+ AFLAG = 1
45+ elif option == '-c':
46+ CFLAG = 1
47+ elif option == '-d':
48+ DFLAG = 1
49+ elif option == '-e':
50+ for line in string.splitfields(optarg, '\n'):
51+ SCRIPT.append(line)
52+ elif option == '-F':
53+ FS = optarg
54+ elif option == '-n':
55+ NFLAG = 1
56+ PFLAG = 0
57+ elif option == '-p':
58+ NFLAG = 1
59+ PFLAG = 1
60+ else:
61+ print option, 'not recognized???'
62+
63+if not ARGS: ARGS.append('-')
64+
65+if not SCRIPT:
66+ if ARGS[0] == '-':
67+ fp = sys.stdin
68+ else:
69+ fp = open(ARGS[0], 'r')
70+ while 1:
71+ line = fp.readline()
72+ if not line: break
73+ SCRIPT.append(line[:-1])
74+ del fp
75+ del ARGS[0]
76+ if not ARGS: ARGS.append('-')
77+
78+if CFLAG:
79+ prologue = ['if 0:']
80+ epilogue = []
81+elif NFLAG:
82+ # Note that it is on purpose that AFLAG and PFLAG are
83+ # tested dynamically each time through the loop
84+ prologue = [ \
85+ 'LINECOUNT = 0', \
86+ 'for FILE in ARGS:', \
87+ ' \tif FILE == \'-\':', \
88+ ' \t \tFP = sys.stdin', \
89+ ' \telse:', \
90+ ' \t \tFP = open(FILE, \'r\')', \
91+ ' \tLINENO = 0', \
92+ ' \twhile 1:', \
93+ ' \t \tLINE = FP.readline()', \
94+ ' \t \tif not LINE: break', \
95+ ' \t \tLINENO = LINENO + 1', \
96+ ' \t \tLINECOUNT = LINECOUNT + 1', \
97+ ' \t \tL = LINE[:-1]', \
98+ ' \t \taflag = AFLAG', \
99+ ' \t \tif aflag:', \
100+ ' \t \t \tif FS: F = string.splitfields(L, FS)', \
101+ ' \t \t \telse: F = string.split(L)' \
102+ ]
103+ epilogue = [ \
104+ ' \t \tif not PFLAG: continue', \
105+ ' \t \tif aflag:', \
106+ ' \t \t \tif FS: print string.joinfields(F, FS)', \
107+ ' \t \t \telse: print string.join(F)', \
108+ ' \t \telse: print L', \
109+ ]
110+else:
111+ prologue = ['if 1:']
112+ epilogue = []
113+
114+# Note that we indent using tabs only, so that any indentation style
115+# used in 'command' will come out right after re-indentation.
116+
117+program = string.joinfields(prologue, '\n') + '\n'
118+for line in SCRIPT:
119+ program = program + (' \t \t' + line + '\n')
120+program = program + (string.joinfields(epilogue, '\n') + '\n')
121+
122+import tempfile
123+fp = tempfile.NamedTemporaryFile()
124+fp.write(program)
125+fp.flush()
126+if DFLAG:
127+ import pdb
128+ pdb.run('execfile(%r)' % (tfn,))
129+else:
130+ execfile(tfn)
sys/src/cmd/python/Demo/scripts/primes.py+27−0
@@ -0,0 +1,27 @@
1+#! /usr/bin/env python
2+
3+# Print prime numbers in a given range
4+
5+def main():
6+ import sys
7+ min, max = 2, 0x7fffffff
8+ if sys.argv[1:]:
9+ min = int(eval(sys.argv[1]))
10+ if sys.argv[2:]:
11+ max = int(eval(sys.argv[2]))
12+ primes(min, max)
13+
14+def primes(min, max):
15+ if 2 >= min: print 2
16+ primes = [2]
17+ i = 3
18+ while i <= max:
19+ for p in primes:
20+ if i%p == 0 or p*p > i: break
21+ if i%p <> 0:
22+ primes.append(i)
23+ if i >= min: print i
24+ i = i+2
25+
26+if __name__ == "__main__":
27+ main()
sys/src/cmd/python/Demo/scripts/queens.py+85−0
@@ -0,0 +1,85 @@
1+#! /usr/bin/env python
2+
3+"""N queens problem.
4+
5+The (well-known) problem is due to Niklaus Wirth.
6+
7+This solution is inspired by Dijkstra (Structured Programming). It is
8+a classic recursive backtracking approach.
9+
10+"""
11+
12+N = 8 # Default; command line overrides
13+
14+class Queens:
15+
16+ def __init__(self, n=N):
17+ self.n = n
18+ self.reset()
19+
20+ def reset(self):
21+ n = self.n
22+ self.y = [None]*n # Where is the queen in column x
23+ self.row = [0]*n # Is row[y] safe?
24+ self.up = [0] * (2*n-1) # Is upward diagonal[x-y] safe?
25+ self.down = [0] * (2*n-1) # Is downward diagonal[x+y] safe?
26+ self.nfound = 0 # Instrumentation
27+
28+ def solve(self, x=0): # Recursive solver
29+ for y in range(self.n):
30+ if self.safe(x, y):
31+ self.place(x, y)
32+ if x+1 == self.n:
33+ self.display()
34+ else:
35+ self.solve(x+1)
36+ self.remove(x, y)
37+
38+ def safe(self, x, y):
39+ return not self.row[y] and not self.up[x-y] and not self.down[x+y]
40+
41+ def place(self, x, y):
42+ self.y[x] = y
43+ self.row[y] = 1
44+ self.up[x-y] = 1
45+ self.down[x+y] = 1
46+
47+ def remove(self, x, y):
48+ self.y[x] = None
49+ self.row[y] = 0
50+ self.up[x-y] = 0
51+ self.down[x+y] = 0
52+
53+ silent = 0 # If set, count solutions only
54+
55+ def display(self):
56+ self.nfound = self.nfound + 1
57+ if self.silent:
58+ return
59+ print '+-' + '--'*self.n + '+'
60+ for y in range(self.n-1, -1, -1):
61+ print '|',
62+ for x in range(self.n):
63+ if self.y[x] == y:
64+ print "Q",
65+ else:
66+ print ".",
67+ print '|'
68+ print '+-' + '--'*self.n + '+'
69+
70+def main():
71+ import sys
72+ silent = 0
73+ n = N
74+ if sys.argv[1:2] == ['-n']:
75+ silent = 1
76+ del sys.argv[1]
77+ if sys.argv[1:]:
78+ n = int(sys.argv[1])
79+ q = Queens(n)
80+ q.silent = silent
81+ q.solve()
82+ print "Found", q.nfound, "solutions."
83+
84+if __name__ == "__main__":
85+ main()
sys/src/cmd/python/Demo/scripts/script.py+33−0
@@ -0,0 +1,33 @@
1+#! /usr/bin/env python
2+# script.py -- Make typescript of terminal session.
3+# Usage:
4+# -a Append to typescript.
5+# -p Use Python as shell.
6+# Author: Steen Lumholt.
7+
8+
9+import os, time, sys
10+import pty
11+
12+def read(fd):
13+ data = os.read(fd, 1024)
14+ file.write(data)
15+ return data
16+
17+shell = 'sh'
18+filename = 'typescript'
19+mode = 'w'
20+if os.environ.has_key('SHELL'):
21+ shell = os.environ['SHELL']
22+if '-a' in sys.argv:
23+ mode = 'a'
24+if '-p' in sys.argv:
25+ shell = 'python'
26+
27+file = open(filename, mode)
28+
29+sys.stdout.write('Script started, file is %s\n' % filename)
30+file.write('Script started on %s\n' % time.ctime(time.time()))
31+pty.spawn(shell, read)
32+file.write('Script done on %s\n' % time.ctime(time.time()))
33+sys.stdout.write('Script done, file is %s\n' % filename)
sys/src/cmd/python/Demo/scripts/unbirthday.py+107−0
@@ -0,0 +1,107 @@
1+#! /usr/bin/env python
2+
3+# Calculate your unbirthday count (see Alice in Wonderland).
4+# This is defined as the number of days from your birth until today
5+# that weren't your birthday. (The day you were born is not counted).
6+# Leap years make it interesting.
7+
8+import sys
9+import time
10+import calendar
11+
12+def main():
13+ # Note that the range checks below also check for bad types,
14+ # e.g. 3.14 or (). However syntactically invalid replies
15+ # will raise an exception.
16+ if sys.argv[1:]:
17+ year = int(sys.argv[1])
18+ else:
19+ year = int(raw_input('In which year were you born? '))
20+ if 0<=year<100:
21+ print "I'll assume that by", year,
22+ year = year + 1900
23+ print 'you mean', year, 'and not the early Christian era'
24+ elif not (1850<=year<=2002):
25+ print "It's hard to believe you were born in", year
26+ return
27+ #
28+ if sys.argv[2:]:
29+ month = int(sys.argv[2])
30+ else:
31+ month = int(raw_input('And in which month? (1-12) '))
32+ if not (1<=month<=12):
33+ print 'There is no month numbered', month
34+ return
35+ #
36+ if sys.argv[3:]:
37+ day = int(sys.argv[3])
38+ else:
39+ day = int(raw_input('And on what day of that month? (1-31) '))
40+ if month == 2 and calendar.isleap(year):
41+ maxday = 29
42+ else:
43+ maxday = calendar.mdays[month]
44+ if not (1<=day<=maxday):
45+ print 'There are no', day, 'days in that month!'
46+ return
47+ #
48+ bdaytuple = (year, month, day)
49+ bdaydate = mkdate(bdaytuple)
50+ print 'You were born on', format(bdaytuple)
51+ #
52+ todaytuple = time.localtime()[:3]
53+ todaydate = mkdate(todaytuple)
54+ print 'Today is', format(todaytuple)
55+ #
56+ if bdaytuple > todaytuple:
57+ print 'You are a time traveler. Go back to the future!'
58+ return
59+ #
60+ if bdaytuple == todaytuple:
61+ print 'You were born today. Have a nice life!'
62+ return
63+ #
64+ days = todaydate - bdaydate
65+ print 'You have lived', days, 'days'
66+ #
67+ age = 0
68+ for y in range(year, todaytuple[0] + 1):
69+ if bdaytuple < (y, month, day) <= todaytuple:
70+ age = age + 1
71+ #
72+ print 'You are', age, 'years old'
73+ #
74+ if todaytuple[1:] == bdaytuple[1:]:
75+ print 'Congratulations! Today is your', nth(age), 'birthday'
76+ print 'Yesterday was your',
77+ else:
78+ print 'Today is your',
79+ print nth(days - age), 'unbirthday'
80+
81+def format((year, month, day)):
82+ return '%d %s %d' % (day, calendar.month_name[month], year)
83+
84+def nth(n):
85+ if n == 1: return '1st'
86+ if n == 2: return '2nd'
87+ if n == 3: return '3rd'
88+ return '%dth' % n
89+
90+def mkdate((year, month, day)):
91+ # Januari 1st, in 0 A.D. is arbitrarily defined to be day 1,
92+ # even though that day never actually existed and the calendar
93+ # was different then...
94+ days = year*365 # years, roughly
95+ days = days + (year+3)/4 # plus leap years, roughly
96+ days = days - (year+99)/100 # minus non-leap years every century
97+ days = days + (year+399)/400 # plus leap years every 4 centirues
98+ for i in range(1, month):
99+ if i == 2 and calendar.isleap(year):
100+ days = days + 29
101+ else:
102+ days = days + calendar.mdays[i]
103+ days = days + day
104+ return days
105+
106+if __name__ == "__main__":
107+ main()
sys/src/cmd/python/Demo/scripts/update.py+92−0
@@ -0,0 +1,92 @@
1+#! /usr/bin/env python
2+
3+# Update a bunch of files according to a script.
4+# The input file contains lines of the form <filename>:<lineno>:<text>,
5+# meaning that the given line of the given file is to be replaced
6+# by the given text. This is useful for performing global substitutions
7+# on grep output:
8+
9+import os
10+import sys
11+import re
12+
13+pat = '^([^: \t\n]+):([1-9][0-9]*):'
14+prog = re.compile(pat)
15+
16+class FileObj:
17+ def __init__(self, filename):
18+ self.filename = filename
19+ self.changed = 0
20+ try:
21+ self.lines = open(filename, 'r').readlines()
22+ except IOError, msg:
23+ print '*** Can\'t open "%s":' % filename, msg
24+ self.lines = None
25+ return
26+ print 'diffing', self.filename
27+
28+ def finish(self):
29+ if not self.changed:
30+ print 'no changes to', self.filename
31+ return
32+ try:
33+ os.rename(self.filename, self.filename + '~')
34+ fp = open(self.filename, 'w')
35+ except (os.error, IOError), msg:
36+ print '*** Can\'t rewrite "%s":' % self.filename, msg
37+ return
38+ print 'writing', self.filename
39+ for line in self.lines:
40+ fp.write(line)
41+ fp.close()
42+ self.changed = 0
43+
44+ def process(self, lineno, rest):
45+ if self.lines is None:
46+ print '(not processed): %s:%s:%s' % (
47+ self.filename, lineno, rest),
48+ return
49+ i = eval(lineno) - 1
50+ if not 0 <= i < len(self.lines):
51+ print '*** Line number out of range: %s:%s:%s' % (
52+ self.filename, lineno, rest),
53+ return
54+ if self.lines[i] == rest:
55+ print '(no change): %s:%s:%s' % (
56+ self.filename, lineno, rest),
57+ return
58+ if not self.changed:
59+ self.changed = 1
60+ print '%sc%s' % (lineno, lineno)
61+ print '<', self.lines[i],
62+ print '---'
63+ self.lines[i] = rest
64+ print '>', self.lines[i],
65+
66+def main():
67+ if sys.argv[1:]:
68+ try:
69+ fp = open(sys.argv[1], 'r')
70+ except IOError, msg:
71+ print 'Can\'t open "%s":' % sys.argv[1], msg
72+ sys.exit(1)
73+ else:
74+ fp = sys.stdin
75+ curfile = None
76+ while 1:
77+ line = fp.readline()
78+ if not line:
79+ if curfile: curfile.finish()
80+ break
81+ n = prog.match(line)
82+ if n < 0:
83+ print 'Funny line:', line,
84+ continue
85+ filename, lineno = prog.group(1, 2)
86+ if not curfile or filename <> curfile.filename:
87+ if curfile: curfile.finish()
88+ curfile = FileObj(filename)
89+ curfile.process(lineno, line[n:])
90+
91+if __name__ == "__main__":
92+ main()
sys/src/cmd/python/Demo/scripts/wh.py+2−0
@@ -0,0 +1,2 @@
1+# This is here so I can use 'wh' instead of 'which' in '~/bin/generic_python'
2+import which