Kaydet (Commit) 4cf83f4d authored tarafından Georg Brandl's avatar Georg Brandl

Remove some of the old demos. (Put a few somewhere else.)

üst d1fc34d5
CGI Examples
------------
Here are some example CGI programs.
cgi0.sh -- A shell script to test your server is configured for CGI
cgi1.py -- A Python script to test your server is configured for CGI
cgi2.py -- A Python script showing how to parse a form
cgi3.py -- A Python script for driving an arbitrary CGI application
wiki.py -- Sample CGI application: a minimal Wiki implementation
#! /bin/sh
# If you can't get this to work, your web server isn't set up right
echo Content-type: text/plain
echo
echo Hello world
echo This is cgi0.sh
#!/usr/bin/env python3
"""CGI test 1 - check server setup."""
# Until you get this to work, your web server isn't set up right or
# your Python isn't set up right.
# If cgi0.sh works but cgi1.py doesn't, check the #! line and the file
# permissions. The docs for the cgi.py module have debugging tips.
print("Content-type: text/html")
print()
print("<h1>Hello world</h1>")
print("<p>This is cgi1.py")
#!/usr/bin/env python3
"""CGI test 2 - basic use of cgi module."""
import cgitb; cgitb.enable()
import cgi
def main():
form = cgi.FieldStorage()
print("Content-type: text/html")
print()
if not form:
print("<h1>No Form Keys</h1>")
else:
print("<h1>Form Keys</h1>")
for key in form.keys():
value = form[key].value
print("<p>", cgi.escape(key), ":", cgi.escape(value))
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""CGI test 3 (persistent data)."""
import cgitb; cgitb.enable()
from wiki import main
if __name__ == "__main__":
main()
"""Wiki main program. Imported and run by cgi3.py."""
import os, re, cgi, sys, tempfile
escape = cgi.escape
def main():
form = cgi.FieldStorage()
print("Content-type: text/html")
print()
cmd = form.getvalue("cmd", "view")
page = form.getvalue("page", "FrontPage")
wiki = WikiPage(page)
method = getattr(wiki, 'cmd_' + cmd, None) or wiki.cmd_view
method(form)
class WikiPage:
homedir = tempfile.gettempdir()
scripturl = os.path.basename(sys.argv[0])
def __init__(self, name):
if not self.iswikiword(name):
raise ValueError("page name is not a wiki word")
self.name = name
self.load()
def cmd_view(self, form):
print("<h1>", escape(self.splitwikiword(self.name)), "</h1>")
print("<p>")
for line in self.data.splitlines():
line = line.rstrip()
if not line:
print("<p>")
else:
print(self.formatline(line))
print("<hr>")
print("<p>", self.mklink("edit", self.name, "Edit this page") + ";")
print(self.mklink("view", "FrontPage", "go to front page") + ".")
def formatline(self, line):
words = []
for word in re.split('(\W+)', line):
if self.iswikiword(word):
if os.path.isfile(self.mkfile(word)):
word = self.mklink("view", word, word)
else:
word = self.mklink("new", word, word + "*")
else:
word = escape(word)
words.append(word)
return "".join(words)
def cmd_edit(self, form, label="Change"):
print("<h1>", label, self.name, "</h1>")
print('<form method="POST" action="%s">' % self.scripturl)
s = '<textarea cols="70" rows="20" name="text">%s</textarea>'
print(s % self.data)
print('<input type="hidden" name="cmd" value="create">')
print('<input type="hidden" name="page" value="%s">' % self.name)
print('<br>')
print('<input type="submit" value="%s Page">' % label)
print("</form>")
def cmd_create(self, form):
self.data = form.getvalue("text", "").strip()
error = self.store()
if error:
print("<h1>I'm sorry. That didn't work</h1>")
print("<p>An error occurred while attempting to write the file:")
print("<p>", escape(error))
else:
# Use a redirect directive, to avoid "reload page" problems
print("<head>")
s = '<meta http-equiv="refresh" content="1; URL=%s">'
print(s % (self.scripturl + "?cmd=view&page=" + self.name))
print("<head>")
print("<h1>OK</h1>")
print("<p>If nothing happens, please click here:", end=' ')
print(self.mklink("view", self.name, self.name))
def cmd_new(self, form):
self.cmd_edit(form, label="Create")
def iswikiword(self, word):
return re.match("[A-Z][a-z]+([A-Z][a-z]*)+", word)
def splitwikiword(self, word):
chars = []
for c in word:
if chars and c.isupper():
chars.append(' ')
chars.append(c)
return "".join(chars)
def mkfile(self, name=None):
if name is None:
name = self.name
return os.path.join(self.homedir, name + ".txt")
def mklink(self, cmd, page, text):
link = self.scripturl + "?cmd=" + cmd + "&page=" + page
return '<a href="%s">%s</a>' % (link, text)
def load(self):
try:
f = open(self.mkfile())
data = f.read().strip()
f.close()
except IOError:
data = ""
self.data = data
def store(self):
data = self.data
try:
f = open(self.mkfile(), "w")
f.write(data)
if data and not data.endswith('\n'):
f.write('\n')
f.close()
return ""
except IOError as err:
return "IOError: %s" % str(err)
Subject: Re: What language would you use?
From: Tom Christiansen <tchrist@mox.perl.com>
Date: 6 Nov 1994 15:14:51 GMT
Newsgroups: comp.lang.python,comp.lang.tcl,comp.lang.scheme,comp.lang.misc,comp.lang.perl
Message-Id: <39irtb$3t4@csnews.cs.Colorado.EDU>
References: <39b7ha$j9v@zeno.nscf.org> <39hhjp$lgn@csnews.cs.Colorado.EDU> <39hvsu$dus@mathserv.mps.ohio-state.edu>
[...]
If you're really into benchmarks, I'd love it if someone were to code up
the following problems in tcl, python, and scheme (and whatever else you'd
like). Separate versions (one optimized for speed, one for beauty :-) are
ok. Post your code so we can time it on our own systems.
0) Factorial Test (numerics and function calls)
(we did this already)
1) Regular Expressions Test
Read a file of (extended per egrep) regular expressions (one per line),
and apply those to all files whose names are listed on the command line.
Basically, an 'egrep -f' simulator. Test it with 20 "vt100" patterns
against a five /etc/termcap files. Tests using more elaborate patters
would also be interesting. Your code should not break if given hundreds
of regular expressions or binary files to scan.
2) Sorting Test
Sort an input file that consists of lines like this
var1=23 other=14 ditto=23 fred=2
such that each output line is sorted WRT to the number. Order
of output lines does not change. Resolve collisions using the
variable name. e.g.
fred=2 other=14 ditto=23 var1=23
Lines may be up to several kilobytes in length and contain
zillions of variables.
3) System Test
Given a list of directories, report any bogus symbolic links contained
anywhere in those subtrees. A bogus symbolic link is one that cannot
be resolved because it points to a nonexistent or otherwise
unresolvable file. Do *not* use an external find executable.
Directories may be very very deep. Print a warning immediately if the
system you're running on doesn't support symbolic links.
I'll post perl solutions if people post the others.
--tom
--
Tom Christiansen Perl Consultant, Gamer, Hiker tchrist@mox.perl.com
"But Billy! A *small* allowance prepares you for a lifetime of small
salaries and for your Social Security payments." --Family Circus
#! /usr/bin/env python3
# 1) Regular Expressions Test
#
# Read a file of (extended per egrep) regular expressions (one per line),
# and apply those to all files whose names are listed on the command line.
# Basically, an 'egrep -f' simulator. Test it with 20 "vt100" patterns
# against a five /etc/termcap files. Tests using more elaborate patters
# would also be interesting. Your code should not break if given hundreds
# of regular expressions or binary files to scan.
# This implementation:
# - combines all patterns into a single one using ( ... | ... | ... )
# - reads patterns from stdin, scans files given as command line arguments
# - produces output in the format <file>:<lineno>:<line>
# - is only about 2.5 times as slow as egrep (though I couldn't run
# Tom's test -- this system, a vanilla SGI, only has /etc/terminfo)
import string
import sys
import re
def main():
pats = list(map(chomp, sys.stdin.readlines()))
bigpat = '(' + '|'.join(pats) + ')'
prog = re.compile(bigpat)
for file in sys.argv[1:]:
try:
fp = open(file, 'r')
except IOError as msg:
print("%s: %s" % (file, msg))
continue
lineno = 0
while 1:
line = fp.readline()
if not line:
break
lineno = lineno + 1
if prog.search(line):
print("%s:%s:%s" % (file, lineno, line), end=' ')
def chomp(s):
return s.rstrip('\n')
if __name__ == '__main__':
main()
#! /usr/bin/env python3
# 2) Sorting Test
#
# Sort an input file that consists of lines like this
#
# var1=23 other=14 ditto=23 fred=2
#
# such that each output line is sorted WRT to the number. Order
# of output lines does not change. Resolve collisions using the
# variable name. e.g.
#
# fred=2 other=14 ditto=23 var1=23
#
# Lines may be up to several kilobytes in length and contain
# zillions of variables.
# This implementation:
# - Reads stdin, writes stdout
# - Uses any amount of whitespace to separate fields
# - Allows signed numbers
# - Treats illegally formatted fields as field=0
# - Outputs the sorted fields with exactly one space between them
# - Handles blank input lines correctly
import re
import sys
def main():
prog = re.compile('^(.*)=([-+]?[0-9]+)')
def makekey(item, prog=prog):
match = prog.match(item)
if match:
var, num = match.groups()
return int(num), var
else:
# Bad input -- pretend it's a var with value 0
return 0, item
for line in sys.stdin:
items = sorted(makekey(item) for item in line.split())
for num, var in items:
print("%s=%s" % (var, num), end=' ')
print()
main()
#! /usr/bin/env python3
# 3) System Test
#
# Given a list of directories, report any bogus symbolic links contained
# anywhere in those subtrees. A bogus symbolic link is one that cannot
# be resolved because it points to a nonexistent or otherwise
# unresolvable file. Do *not* use an external find executable.
# Directories may be very very deep. Print a warning immediately if the
# system you're running on doesn't support symbolic links.
# This implementation:
# - takes one optional argument, using the current directory as default
# - uses chdir to increase performance
# - sorts the names per directory
# - prints output lines of the form "path1 -> path2" as it goes
# - prints error messages about directories it can't list or chdir into
import os
import sys
from stat import *
def main():
try:
# Note: can't test for presence of lstat -- it's always there
dummy = os.readlink
except AttributeError:
print("This system doesn't have symbolic links")
sys.exit(0)
if sys.argv[1:]:
prefix = sys.argv[1]
else:
prefix = ''
if prefix:
os.chdir(prefix)
if prefix[-1:] != '/': prefix = prefix + '/'
reportboguslinks(prefix)
else:
reportboguslinks('')
def reportboguslinks(prefix):
try:
names = os.listdir('.')
except os.error as msg:
print("%s%s: can't list: %s" % (prefix, '.', msg))
return
names.sort()
for name in names:
if name == os.curdir or name == os.pardir:
continue
try:
mode = os.lstat(name)[ST_MODE]
except os.error:
print("%s%s: can't stat: %s" % (prefix, name, msg))
continue
if S_ISLNK(mode):
try:
os.stat(name)
except os.error:
print("%s%s -> %s" % \
(prefix, name, os.readlink(name)))
elif S_ISDIR(mode):
try:
os.chdir(name)
except os.error as msg:
print("%s%s: can't chdir: %s" % \
(prefix, name, msg))
continue
try:
reportboguslinks(prefix + name + '/')
finally:
os.chdir('..')
main()
#!/usr/bin/env python3
#
# $Id$
#
# (n)curses exerciser in Python, an interactive test for the curses
# module. Currently, only the panel demos are ported.
import curses
from curses import panel
def wGetchar(win = None):
if win is None: win = stdscr
return win.getch()
def Getchar():
wGetchar()
#
# Panels tester
#
def wait_a_while():
if nap_msec == 1:
Getchar()
else:
curses.napms(nap_msec)
def saywhat(text):
stdscr.move(curses.LINES - 1, 0)
stdscr.clrtoeol()
stdscr.addstr(text)
def mkpanel(color, rows, cols, tly, tlx):
win = curses.newwin(rows, cols, tly, tlx)
pan = panel.new_panel(win)
if curses.has_colors():
if color == curses.COLOR_BLUE:
fg = curses.COLOR_WHITE
else:
fg = curses.COLOR_BLACK
bg = color
curses.init_pair(color, fg, bg)
win.bkgdset(ord(' '), curses.color_pair(color))
else:
win.bkgdset(ord(' '), curses.A_BOLD)
return pan
def pflush():
panel.update_panels()
curses.doupdate()
def fill_panel(pan):
win = pan.window()
num = pan.userptr()[1]
win.move(1, 1)
win.addstr("-pan%c-" % num)
win.clrtoeol()
win.box()
maxy, maxx = win.getmaxyx()
for y in range(2, maxy - 1):
for x in range(1, maxx - 1):
win.move(y, x)
win.addch(num)
def demo_panels(win):
global stdscr, nap_msec, mod
stdscr = win
nap_msec = 1
mod = ["test", "TEST", "(**)", "*()*", "<-->", "LAST"]
stdscr.refresh()
for y in range(0, curses.LINES - 1):
for x in range(0, curses.COLS):
stdscr.addstr("%d" % ((y + x) % 10))
for y in range(0, 1):
p1 = mkpanel(curses.COLOR_RED,
curses.LINES // 2 - 2,
curses.COLS // 8 + 1,
0,
0)
p1.set_userptr("p1")
p2 = mkpanel(curses.COLOR_GREEN,
curses.LINES // 2 + 1,
curses.COLS // 7,
curses.LINES // 4,
curses.COLS // 10)
p2.set_userptr("p2")
p3 = mkpanel(curses.COLOR_YELLOW,
curses.LINES // 4,
curses.COLS // 10,
curses.LINES // 2,
curses.COLS // 9)
p3.set_userptr("p3")
p4 = mkpanel(curses.COLOR_BLUE,
curses.LINES // 2 - 2,
curses.COLS // 8,
curses.LINES // 2 - 2,
curses.COLS // 3)
p4.set_userptr("p4")
p5 = mkpanel(curses.COLOR_MAGENTA,
curses.LINES // 2 - 2,
curses.COLS // 8,
curses.LINES // 2,
curses.COLS // 2 - 2)
p5.set_userptr("p5")
fill_panel(p1)
fill_panel(p2)
fill_panel(p3)
fill_panel(p4)
fill_panel(p5)
p4.hide()
p5.hide()
pflush()
saywhat("press any key to continue")
wait_a_while()
saywhat("h3 s1 s2 s4 s5;press any key to continue")
p1.move(0, 0)
p3.hide()
p1.show()
p2.show()
p4.show()
p5.show()
pflush()
wait_a_while()
saywhat("s1; press any key to continue")
p1.show()
pflush()
wait_a_while()
saywhat("s2; press any key to continue")
p2.show()
pflush()
wait_a_while()
saywhat("m2; press any key to continue")
p2.move(curses.LINES // 3 + 1, curses.COLS // 8)
pflush()
wait_a_while()
saywhat("s3; press any key to continue")
p3.show()
pflush()
wait_a_while()
saywhat("m3; press any key to continue")
p3.move(curses.LINES // 4 + 1, curses.COLS // 15)
pflush()
wait_a_while()
saywhat("b3; press any key to continue")
p3.bottom()
pflush()
wait_a_while()
saywhat("s4; press any key to continue")
p4.show()
pflush()
wait_a_while()
saywhat("s5; press any key to continue")
p5.show()
pflush()
wait_a_while()
saywhat("t3; press any key to continue")
p3.top()
pflush()
wait_a_while()
saywhat("t1; press any key to continue")
p1.show()
pflush()
wait_a_while()
saywhat("t2; press any key to continue")
p2.show()
pflush()
wait_a_while()
saywhat("t3; press any key to continue")
p3.show()
pflush()
wait_a_while()
saywhat("t4; press any key to continue")
p4.show()
pflush()
wait_a_while()
for itmp in range(0, 6):
w4 = p4.window()
w5 = p5.window()
saywhat("m4; press any key to continue")
w4.move(curses.LINES // 8, 1)
w4.addstr(mod[itmp])
p4.move(curses.LINES // 6, itmp * curses.COLS // 8)
w5.move(curses.LINES // 6, 1)
w5.addstr(mod[itmp])
pflush()
wait_a_while()
saywhat("m5; press any key to continue")
w4.move(curses.LINES // 6, 1)
w4.addstr(mod[itmp])
p5.move(curses.LINES // 3 - 1, itmp * 10 + 6)
w5.move(curses.LINES // 8, 1)
w5.addstr(mod[itmp])
pflush()
wait_a_while()
saywhat("m4; press any key to continue")
p4.move(curses.LINES // 6, (itmp + 1) * curses.COLS // 8)
pflush()
wait_a_while()
saywhat("t5; press any key to continue")
p5.top()
pflush()
wait_a_while()
saywhat("t2; press any key to continue")
p2.top()
pflush()
wait_a_while()
saywhat("t1; press any key to continue")
p1.top()
pflush()
wait_a_while()
saywhat("d2; press any key to continue")
del p2
pflush()
wait_a_while()
saywhat("h3; press any key to continue")
p3.hide()
pflush()
wait_a_while()
saywhat("d1; press any key to continue")
del p1
pflush()
wait_a_while()
saywhat("d4; press any key to continue")
del p4
pflush()
wait_a_while()
saywhat("d5; press any key to continue")
del p5
pflush()
wait_a_while()
if nap_msec == 1:
break
nap_msec = 100
#
# one fine day there'll be the menu at this place
#
curses.wrapper(demo_panels)
#!/usr/bin/env python3
#
# $Id$
#
# somebody should probably check the randrange()s...
import curses
from random import randrange
def next_j(j):
if j == 0:
j = 4
else:
j -= 1
if curses.has_colors():
z = randrange(0, 3)
color = curses.color_pair(z)
if z:
color = color | curses.A_BOLD
stdscr.attrset(color)
return j
def main(win):
# we know that the first argument from curses.wrapper() is stdscr.
# Initialize it globally for convenience.
global stdscr
stdscr = win
if curses.has_colors():
bg = curses.COLOR_BLACK
curses.init_pair(1, curses.COLOR_BLUE, bg)
curses.init_pair(2, curses.COLOR_CYAN, bg)
curses.nl()
curses.noecho()
# XXX curs_set() always returns ERR
# curses.curs_set(0)
stdscr.timeout(0)
c = curses.COLS - 4
r = curses.LINES - 4
xpos = [0] * c
ypos = [0] * r
for j in range(4, -1, -1):
xpos[j] = randrange(0, c) + 2
ypos[j] = randrange(0, r) + 2
j = 0
while True:
x = randrange(0, c) + 2
y = randrange(0, r) + 2
stdscr.addch(y, x, ord('.'))
stdscr.addch(ypos[j], xpos[j], ord('o'))
j = next_j(j)
stdscr.addch(ypos[j], xpos[j], ord('O'))
j = next_j(j)
stdscr.addch( ypos[j] - 1, xpos[j], ord('-'))
stdscr.addstr(ypos[j], xpos[j] - 1, "|.|")
stdscr.addch( ypos[j] + 1, xpos[j], ord('-'))
j = next_j(j)
stdscr.addch( ypos[j] - 2, xpos[j], ord('-'))
stdscr.addstr(ypos[j] - 1, xpos[j] - 1, "/ \\")
stdscr.addstr(ypos[j], xpos[j] - 2, "| O |")
stdscr.addstr(ypos[j] + 1, xpos[j] - 1, "\\ /")
stdscr.addch( ypos[j] + 2, xpos[j], ord('-'))
j = next_j(j)
stdscr.addch( ypos[j] - 2, xpos[j], ord(' '))
stdscr.addstr(ypos[j] - 1, xpos[j] - 1, " ")
stdscr.addstr(ypos[j], xpos[j] - 2, " ")
stdscr.addstr(ypos[j] + 1, xpos[j] - 1, " ")
stdscr.addch( ypos[j] + 2, xpos[j], ord(' '))
xpos[j] = x
ypos[j] = y
ch = stdscr.getch()
if ch == ord('q') or ch == ord('Q'):
return
elif ch == ord('s'):
stdscr.nodelay(0)
elif ch == ord(' '):
stdscr.nodelay(1)
curses.napms(50)
curses.wrapper(main)
#!/usr/bin/env python3
#
# $Id$
#
# From tclock.c, Copyright Howard Jones <ha.jones@ic.ac.uk>, September 1994.
from math import *
import curses, time
ASPECT = 2.2
def sign(_x):
if _x < 0: return -1
return 1
def A2XY(angle, radius):
return (int(round(ASPECT * radius * sin(angle))),
int(round(radius * cos(angle))))
def plot(x, y, col):
stdscr.addch(y, x, col)
# draw a diagonal line using Bresenham's algorithm
def dline(pair, from_x, from_y, x2, y2, ch):
if curses.has_colors():
stdscr.attrset(curses.color_pair(pair))
dx = x2 - from_x
dy = y2 - from_y
ax = abs(dx * 2)
ay = abs(dy * 2)
sx = sign(dx)
sy = sign(dy)
x = from_x
y = from_y
if ax > ay:
d = ay - ax // 2
while True:
plot(x, y, ch)
if x == x2:
return
if d >= 0:
y += sy
d -= ax
x += sx
d += ay
else:
d = ax - ay // 2
while True:
plot(x, y, ch)
if y == y2:
return
if d >= 0:
x += sx
d -= ay
y += sy
d += ax
def main(win):
global stdscr
stdscr = win
lastbeep = -1
my_bg = curses.COLOR_BLACK
stdscr.nodelay(1)
stdscr.timeout(0)
# curses.curs_set(0)
if curses.has_colors():
curses.init_pair(1, curses.COLOR_RED, my_bg)
curses.init_pair(2, curses.COLOR_MAGENTA, my_bg)
curses.init_pair(3, curses.COLOR_GREEN, my_bg)
cx = (curses.COLS - 1) // 2
cy = curses.LINES // 2
ch = min( cy-1, int(cx // ASPECT) - 1)
mradius = (3 * ch) // 4
hradius = ch // 2
sradius = 5 * ch // 6
for i in range(0, 12):
sangle = (i + 1) * 2.0 * pi / 12.0
sdx, sdy = A2XY(sangle, sradius)
stdscr.addstr(cy - sdy, cx + sdx, "%d" % (i + 1))
stdscr.addstr(0, 0,
"ASCII Clock by Howard Jones <ha.jones@ic.ac.uk>, 1994")
sradius = max(sradius-4, 8)
while True:
curses.napms(1000)
tim = time.time()
t = time.localtime(tim)
hours = t[3] + t[4] / 60.0
if hours > 12.0:
hours -= 12.0
mangle = t[4] * 2 * pi / 60.0
mdx, mdy = A2XY(mangle, mradius)
hangle = hours * 2 * pi / 12.0
hdx, hdy = A2XY(hangle, hradius)
sangle = t[5] * 2 * pi / 60.0
sdx, sdy = A2XY(sangle, sradius)
dline(3, cx, cy, cx + mdx, cy - mdy, ord('#'))
stdscr.attrset(curses.A_REVERSE)
dline(2, cx, cy, cx + hdx, cy - hdy, ord('.'))
stdscr.attroff(curses.A_REVERSE)
if curses.has_colors():
stdscr.attrset(curses.color_pair(1))
plot(cx + sdx, cy - sdy, ord('O'))
if curses.has_colors():
stdscr.attrset(curses.color_pair(0))
stdscr.addstr(curses.LINES - 2, 0, time.ctime(tim))
stdscr.refresh()
if (t[5] % 5) == 0 and t[5] != lastbeep:
lastbeep = t[5]
curses.beep()
ch = stdscr.getch()
if ch == ord('q'):
return 0
plot(cx + sdx, cy - sdy, ord(' '))
dline(0, cx, cy, cx + hdx, cy - hdy, ord(' '))
dline(0, cx, cy, cx + mdx, cy - mdy, ord(' '))
curses.wrapper(main)
This diff is collapsed.
This is the Python version of the MD5 test program from the MD5
Internet Draft (Rivest and Dusse, The MD5 Message-Digest Algorithm, 10
July 1991). The file "foo" contains the string "abc" with no trailing
newline.
When called without arguments, it acts as a filter. When called with
"-x", it executes a self-test, and the output should literally match
the output given in the RFC.
Code by Jan-Hein B\"uhrman after the original in C.
abc
\ No newline at end of file
from hashlib import md5
import string
from sys import argv
def MDPrint(str):
outstr = ''
for o in str:
outstr = (outstr
+ string.hexdigits[(o >> 4) & 0xF]
+ string.hexdigits[o & 0xF])
print(outstr, end=' ')
from time import time
def makestr(start, end):
result = ''
for i in range(start, end + 1):
result = result + chr(i)
return result
def MDTimeTrial():
TEST_BLOCK_SIZE = 1000
TEST_BLOCKS = 10000
TEST_BYTES = TEST_BLOCK_SIZE * TEST_BLOCKS
# initialize test data, need temporary string filler
filsiz = 1 << 8
filler = makestr(0, filsiz-1)
data = filler * (TEST_BLOCK_SIZE // filsiz)
data = data + filler[:(TEST_BLOCK_SIZE % filsiz)]
del filsiz, filler
# start timer
print('MD5 time trial. Processing', TEST_BYTES, 'characters...')
t1 = time()
mdContext = md5()
for i in range(TEST_BLOCKS):
mdContext.update(data)
str = mdContext.digest()
t2 = time()
MDPrint(str)
print('is digest of test input.')
print('Seconds to process test input:', t2 - t1)
print('Characters processed per second:', TEST_BYTES / (t2 - t1))
def MDString(str):
MDPrint(md5(str.encode("utf-8")).digest())
print('"' + str + '"')
def MDFile(filename):
f = open(filename, 'rb')
mdContext = md5()
while 1:
data = f.read(1024)
if not data:
break
mdContext.update(data)
MDPrint(mdContext.digest())
print(filename)
import sys
def MDFilter():
mdContext = md5()
while 1:
data = sys.stdin.read(16).encode()
if not data:
break
mdContext.update(data)
MDPrint(mdContext.digest())
print()
def MDTestSuite():
print('MD5 test suite results:')
MDString('')
MDString('a')
MDString('abc')
MDString('message digest')
MDString(makestr(ord('a'), ord('z')))
MDString(makestr(ord('A'), ord('Z'))
+ makestr(ord('a'), ord('z'))
+ makestr(ord('0'), ord('9')))
MDString((makestr(ord('1'), ord('9')) + '0') * 8)
# Contents of file foo are "abc"
MDFile('foo')
# I don't wanna use getopt(), since I want to use the same i/f...
def main():
if len(argv) == 1:
MDFilter()
for arg in argv[1:]:
if arg[:2] == '-s':
MDString(arg[2:])
elif arg == '-t':
MDTimeTrial()
elif arg == '-x':
MDTestSuite()
else:
MDFile(arg)
main()
Demo/parser
Doc/libparser.tex
Lib/AST.py
Lib/symbol.py
Lib/token.py
Modules/parsermodule.c
These files are from the large example of using the `parser' module. Refer
to the Python Library Reference for more information.
It also contains examples for the AST parser.
Files:
------
FILES -- list of files associated with the parser module.
README -- this file.
example.py -- module that uses the `parser' module to extract
information from the parse tree of Python source
code.
docstring.py -- sample source file containing only a module docstring.
simple.py -- sample source containing a "short form" definition.
source.py -- sample source code used to demonstrate ability to
handle nested constructs easily using the functions
and classes in example.py.
test_parser.py program to put the parser module through its paces.
unparse.py AST (2.5) based example to recreate source code
from an AST. This is incomplete; contributions
are welcome.
Enjoy!
"""Simple code to extract class & function docstrings from a module.
This code is used as an example in the library reference manual in the
section on using the parser module. Refer to the manual for a thorough
discussion of the operation of this code.
"""
import os
import parser
import symbol
import token
import types
from types import ListType, TupleType
def get_docs(fileName):
"""Retrieve information from the parse tree of a source file.
fileName
Name of the file to read Python source code from.
"""
source = open(fileName).read()
basename = os.path.basename(os.path.splitext(fileName)[0])
ast = parser.suite(source)
return ModuleInfo(ast.totuple(), basename)
class SuiteInfoBase:
_docstring = ''
_name = ''
def __init__(self, tree = None):
self._class_info = {}
self._function_info = {}
if tree:
self._extract_info(tree)
def _extract_info(self, tree):
# extract docstring
if len(tree) == 2:
found, vars = match(DOCSTRING_STMT_PATTERN[1], tree[1])
else:
found, vars = match(DOCSTRING_STMT_PATTERN, tree[3])
if found:
self._docstring = eval(vars['docstring'])
# discover inner definitions
for node in tree[1:]:
found, vars = match(COMPOUND_STMT_PATTERN, node)
if found:
cstmt = vars['compound']
if cstmt[0] == symbol.funcdef:
name = cstmt[2][1]
self._function_info[name] = FunctionInfo(cstmt)
elif cstmt[0] == symbol.classdef:
name = cstmt[2][1]
self._class_info[name] = ClassInfo(cstmt)
def get_docstring(self):
return self._docstring
def get_name(self):
return self._name
def get_class_names(self):
return list(self._class_info.keys())
def get_class_info(self, name):
return self._class_info[name]
def __getitem__(self, name):
try:
return self._class_info[name]
except KeyError:
return self._function_info[name]
class SuiteFuncInfo:
# Mixin class providing access to function names and info.
def get_function_names(self):
return list(self._function_info.keys())
def get_function_info(self, name):
return self._function_info[name]
class FunctionInfo(SuiteInfoBase, SuiteFuncInfo):
def __init__(self, tree = None):
self._name = tree[2][1]
SuiteInfoBase.__init__(self, tree and tree[-1] or None)
class ClassInfo(SuiteInfoBase):
def __init__(self, tree = None):
self._name = tree[2][1]
SuiteInfoBase.__init__(self, tree and tree[-1] or None)
def get_method_names(self):
return list(self._function_info.keys())
def get_method_info(self, name):
return self._function_info[name]
class ModuleInfo(SuiteInfoBase, SuiteFuncInfo):
def __init__(self, tree = None, name = "<string>"):
self._name = name
SuiteInfoBase.__init__(self, tree)
if tree:
found, vars = match(DOCSTRING_STMT_PATTERN, tree[1])
if found:
self._docstring = vars["docstring"]
def match(pattern, data, vars=None):
"""Match `data' to `pattern', with variable extraction.
pattern
Pattern to match against, possibly containing variables.
data
Data to be checked and against which variables are extracted.
vars
Dictionary of variables which have already been found. If not
provided, an empty dictionary is created.
The `pattern' value may contain variables of the form ['varname'] which
are allowed to match anything. The value that is matched is returned as
part of a dictionary which maps 'varname' to the matched value. 'varname'
is not required to be a string object, but using strings makes patterns
and the code which uses them more readable.
This function returns two values: a boolean indicating whether a match
was found and a dictionary mapping variable names to their associated
values.
"""
if vars is None:
vars = {}
if type(pattern) is ListType: # 'variables' are ['varname']
vars[pattern[0]] = data
return 1, vars
if type(pattern) is not TupleType:
return (pattern == data), vars
if len(data) != len(pattern):
return 0, vars
for pattern, data in map(None, pattern, data):
same, vars = match(pattern, data, vars)
if not same:
break
return same, vars
# This pattern identifies compound statements, allowing them to be readily
# differentiated from simple statements.
#
COMPOUND_STMT_PATTERN = (
symbol.stmt,
(symbol.compound_stmt, ['compound'])
)
# This pattern will match a 'stmt' node which *might* represent a docstring;
# docstrings require that the statement which provides the docstring be the
# first statement in the class or function, which this pattern does not check.
#
DOCSTRING_STMT_PATTERN = (
symbol.stmt,
(symbol.simple_stmt,
(symbol.small_stmt,
(symbol.expr_stmt,
(symbol.testlist,
(symbol.test,
(symbol.and_test,
(symbol.not_test,
(symbol.comparison,
(symbol.expr,
(symbol.xor_expr,
(symbol.and_expr,
(symbol.shift_expr,
(symbol.arith_expr,
(symbol.term,
(symbol.factor,
(symbol.power,
(symbol.atom,
(token.STRING, ['docstring'])
)))))))))))))))),
(token.NEWLINE, '')
))
"""Exmaple file to be parsed for the parsermodule example.
The classes and functions in this module exist only to exhibit the ability
of the handling information extraction from nested definitions using parse
trees. They shouldn't interest you otherwise!
"""
class Simple:
"This class does very little."
def method(self):
"This method does almost nothing."
return 1
class Nested:
"This is a nested class."
def nested_method(self):
"Method of Nested class."
def nested_function():
"Function in method of Nested class."
pass
return nested_function
def function():
"This function lives at the module level."
return 0
#! /usr/bin/env python3
# (Force the script to use the latest build.)
#
# test_parser.py
import parser, traceback
_numFailed = 0
def testChunk(t, fileName):
global _numFailed
print('----', fileName, end=' ')
try:
st = parser.suite(t)
tup = parser.st2tuple(st)
# this discards the first ST; a huge memory savings when running
# against a large source file like Tkinter.py.
st = None
new = parser.tuple2st(tup)
except parser.ParserError as err:
print()
print('parser module raised exception on input file', fileName + ':')
traceback.print_exc()
_numFailed = _numFailed + 1
else:
if tup != parser.st2tuple(new):
print()
print('parser module failed on input file', fileName)
_numFailed = _numFailed + 1
else:
print('o.k.')
def testFile(fileName):
t = open(fileName).read()
testChunk(t, fileName)
def test():
import sys
args = sys.argv[1:]
if not args:
import glob
args = glob.glob("*.py")
args.sort()
list(map(testFile, args))
sys.exit(_numFailed != 0)
if __name__ == '__main__':
test()
\input texinfo @c -*-texinfo-*-
@c %**start of header
@setfilename parser.info
@settitle Python Parser Module Reference
@setchapternewpage odd
@footnotestyle end
@c %**end of header
@ifinfo
This file describes the interfaces
published by the optional @code{parser} module and gives examples of
how they may be used. It contains the same text as the chapter on the
@code{parser} module in the @cite{Python Library Reference}, but is
presented as a separate document.
Copyright 1995-1996 by Fred L. Drake, Jr., Reston, Virginia, USA, and
Virginia Polytechnic Institute and State University, Blacksburg,
Virginia, USA. Portions of the software copyright 1991-1995 by
Stichting Mathematisch Centrum, Amsterdam, The Netherlands. Copying is
permitted under the terms associated with the main Python distribution,
with the additional restriction that this additional notice be included
and maintained on all distributed copies.
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the names of Fred L. Drake, Jr. and
Virginia Polytechnic Institute and State University not be used in
advertising or publicity pertaining to distribution of the software
without specific, written prior permission.
FRED L. DRAKE, JR. AND VIRGINIA POLYTECHNIC INSTITUTE AND STATE
UNIVERSITY DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
EVENT SHALL FRED L. DRAKE, JR. OR VIRGINIA POLYTECHNIC INSTITUTE AND
STATE UNIVERSITY BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
@end ifinfo
@titlepage
@title Python Parser Module Reference
@author Fred L. Drake, Jr.
@c The following two commands start the copyright page.
@page
@vskip 0pt plus 1filll
Copyright 1995-1996 by Fred L. Drake, Jr., Reston, Virginia, USA, and
Virginia Polytechnic Institute and State University, Blacksburg,
Virginia, USA. Portions of the software copyright 1991-1995 by
Stichting Mathematisch Centrum, Amsterdam, The Netherlands. Copying is
permitted under the terms associated with the main Python distribution,
with the additional restriction that this additional notice be included
and maintained on all distributed copies.
@center All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the names of Fred L. Drake, Jr. and
Virginia Polytechnic Institute and State University not be used in
advertising or publicity pertaining to distribution of the software
without specific, written prior permission.
FRED L. DRAKE, JR. AND VIRGINIA POLYTECHNIC INSTITUTE AND STATE
UNIVERSITY DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
EVENT SHALL FRED L. DRAKE, JR. OR VIRGINIA POLYTECHNIC INSTITUTE AND
STATE UNIVERSITY BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
@end titlepage
@node Top, Overview, (dir), (dir)
@top The Python Parser Module
@ifinfo
This file describes the interfaces
published by the optional @code{parser} module and gives examples of
how they may be used. It contains the same text as the chapter on the
@code{parser} module in the @cite{Python Library Reference}, but is
presented as a separate document.
This version corresponds to Python version 1.4 (1 Sept. 1996).
@end ifinfo
@c placeholder for the master menu -- patched by texinfo-all-menus-update
@menu
@end menu
# Makefile for 'pysvr' application embedding Python.
# Tailored for Python 1.5a3 or later.
# Some details are specific for Solaris or CNRI.
# Also see ## comments for tailoring.
# Which C compiler
CC=gcc
##PURIFY=/usr/local/pure/purify
LINKCC=$(PURIFY) $(CC)
# Optimization preferences
OPT=-g
# Which Python version we're using
VER=2.2
# Expressions using the above definitions
PYVER=python$(VER)
# Use these defs when compiling against installed Python
##INST=/usr/local
##PYC=$(INST)/lib/$(PYVER)/config
##PYINCL=-I$(INST)/include/$(PYVER) -I$(PYC)
##PYLIBS=$(PYC)/lib$(PYVER).a
# Use these defs when compiling against built Python
PLAT=linux
PYINCL=-I../../Include -I../../$(PLAT)
PYLIBS=../../$(PLAT)/lib$(PYVER).a
# Libraries to link with -- very installation dependent
# (See LIBS= in Modules/Makefile in build tree)
RLLIBS=-lreadline -ltermcap
OTHERLIBS=-lnsl -lpthread -ldl -lm -ldb -lutil
# Compilation and link flags -- no need to change normally
CFLAGS=$(OPT)
CPPFLAGS=$(PYINCL)
LIBS=$(PYLIBS) $(RLLIBS) $(OTHERLIBS)
# Default port for the pysvr application
PORT=4000
# Default target
all: pysvr
# Target to build pysvr
pysvr: pysvr.o $(PYOBJS) $(PYLIBS)
$(LINKCC) pysvr.o $(LIBS) -o pysvr
# Target to build and run pysvr
run: pysvr
pysvr $(PORT)
# Target to clean up the directory
clean:
-rm -f pysvr *.o *~ core
This is an example of a multi-threaded C application embedding a
Python interpreter.
The particular application is a multi-threaded telnet-like server that
provides you with a Python prompt (instead of a shell prompt).
The file pysvr.py is a prototype in Python.
THIS APPLICATION IS NOT SECURE -- ONLY USE IT FOR TESTING!
/* A multi-threaded telnet-like server that gives a Python prompt.
Usage: pysvr [port]
For security reasons, it only accepts requests from the current host.
This can still be insecure, but restricts violations from people who
can log in on your machine. Use with caution!
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
#include <getopt.h>
/* XXX Umpfh.
Python.h defines a typedef destructor, which conflicts with pthread.h.
So Python.h must be included after pthread.h. */
#include "Python.h"
extern int Py_VerboseFlag;
#ifndef PORT
#define PORT 4000
#endif
struct workorder {
int conn;
struct sockaddr_in addr;
};
/* Forward */
static void init_python(void);
static void usage(void);
static void oprogname(void);
static void main_thread(int);
static void create_thread(int, struct sockaddr_in *);
static void *service_thread(struct workorder *);
static void run_interpreter(FILE *, FILE *);
static int run_command(char *, PyObject *);
static void ps(void);
static char *progname = "pysvr";
static PyThreadState *gtstate;
main(int argc, char **argv)
{
int port = PORT;
int c;
if (argc > 0 && argv[0] != NULL && argv[0][0] != '\0')
progname = argv[0];
while ((c = getopt(argc, argv, "v")) != EOF) {
switch (c) {
case 'v':
Py_VerboseFlag++;
break;
default:
usage();
}
}
if (optind < argc) {
if (optind+1 < argc) {
oprogname();
fprintf(stderr, "too many arguments\n");
usage();
}
port = atoi(argv[optind]);
if (port <= 0) {
fprintf(stderr, "bad port (%s)\n", argv[optind]);
usage();
}
}
main_thread(port);
fprintf(stderr, "Bye.\n");
exit(0);
}
static char usage_line[] = "usage: %s [port]\n";
static void
usage(void)
{
fprintf(stderr, usage_line, progname);
exit(2);
}
static void
main_thread(int port)
{
int sock, conn, size, i;
struct sockaddr_in addr, clientaddr;
sock = socket(PF_INET, SOCK_STREAM, 0);
if (sock < 0) {
oprogname();
perror("can't create socket");
exit(1);
}
#ifdef SO_REUSEADDR
i = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &i, sizeof i);
#endif
memset((char *)&addr, '\0', sizeof addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = 0L;
if (bind(sock, (struct sockaddr *)&addr, sizeof addr) < 0) {
oprogname();
perror("can't bind socket to address");
exit(1);
}
if (listen(sock, 5) < 0) {
oprogname();
perror("can't listen on socket");
exit(1);
}
fprintf(stderr, "Listening on port %d...\n", port);
for (i = 0; ; i++) {
size = sizeof clientaddr;
memset((char *) &clientaddr, '\0', size);
conn = accept(sock, (struct sockaddr *) &clientaddr, &size);
if (conn < 0) {
oprogname();
perror("can't accept connection from socket");
exit(1);
}
size = sizeof addr;
memset((char *) &addr, '\0', size);
if (getsockname(conn, (struct sockaddr *)&addr, &size) < 0) {
oprogname();
perror("can't get socket name of connection");
exit(1);
}
if (clientaddr.sin_addr.s_addr != addr.sin_addr.s_addr) {
oprogname();
perror("connection from non-local host refused");
fprintf(stderr, "(addr=%lx, clientaddr=%lx)\n",
ntohl(addr.sin_addr.s_addr),
ntohl(clientaddr.sin_addr.s_addr));
close(conn);
continue;
}
if (i == 4) {
close(conn);
break;
}
create_thread(conn, &clientaddr);
}
close(sock);
if (gtstate) {
PyEval_AcquireThread(gtstate);
gtstate = NULL;
Py_Finalize();
/* And a second time, just because we can. */
Py_Finalize(); /* This should be harmless. */
}
exit(0);
}
static void
create_thread(int conn, struct sockaddr_in *addr)
{
struct workorder *work;
pthread_t tdata;
work = malloc(sizeof(struct workorder));
if (work == NULL) {
oprogname();
fprintf(stderr, "out of memory for thread.\n");
close(conn);
return;
}
work->conn = conn;
work->addr = *addr;
init_python();
if (pthread_create(&tdata, NULL, (void *)service_thread, work) < 0) {
oprogname();
perror("can't create new thread");
close(conn);
return;
}
if (pthread_detach(tdata) < 0) {
oprogname();
perror("can't detach from thread");
}
}
static PyThreadState *the_tstate;
static PyInterpreterState *the_interp;
static PyObject *the_builtins;
static void
init_python(void)
{
if (gtstate)
return;
Py_Initialize(); /* Initialize the interpreter */
PyEval_InitThreads(); /* Create (and acquire) the interpreter lock */
gtstate = PyEval_SaveThread(); /* Release the thread state */
}
static void *
service_thread(struct workorder *work)
{
FILE *input, *output;
fprintf(stderr, "Start thread for connection %d.\n", work->conn);
ps();
input = fdopen(work->conn, "r");
if (input == NULL) {
oprogname();
perror("can't create input stream");
goto done;
}
output = fdopen(work->conn, "w");
if (output == NULL) {
oprogname();
perror("can't create output stream");
fclose(input);
goto done;
}
setvbuf(input, NULL, _IONBF, 0);
setvbuf(output, NULL, _IONBF, 0);
run_interpreter(input, output);
fclose(input);
fclose(output);
done:
fprintf(stderr, "End thread for connection %d.\n", work->conn);
close(work->conn);
free(work);
}
static void
oprogname(void)
{
int save = errno;
fprintf(stderr, "%s: ", progname);
errno = save;
}
static void
run_interpreter(FILE *input, FILE *output)
{
PyThreadState *tstate;
PyObject *new_stdin, *new_stdout;
PyObject *mainmod, *globals;
char buffer[1000];
char *p, *q;
int n, end;
PyEval_AcquireLock();
tstate = Py_NewInterpreter();
if (tstate == NULL) {
fprintf(output, "Sorry -- can't create an interpreter\n");
return;
}
mainmod = PyImport_AddModule("__main__");
globals = PyModule_GetDict(mainmod);
Py_INCREF(globals);
new_stdin = PyFile_FromFile(input, "<socket-in>", "r", NULL);
new_stdout = PyFile_FromFile(output, "<socket-out>", "w", NULL);
PySys_SetObject("stdin", new_stdin);
PySys_SetObject("stdout", new_stdout);
PySys_SetObject("stderr", new_stdout);
for (n = 1; !PyErr_Occurred(); n++) {
Py_BEGIN_ALLOW_THREADS
fprintf(output, "%d> ", n);
p = fgets(buffer, sizeof buffer, input);
Py_END_ALLOW_THREADS
if (p == NULL)
break;
if (p[0] == '\377' && p[1] == '\354')
break;
q = strrchr(p, '\r');
if (q && q[1] == '\n' && q[2] == '\0') {
*q++ = '\n';
*q++ = '\0';
}
while (*p && isspace(*p))
p++;
if (p[0] == '#' || p[0] == '\0')
continue;
end = run_command(buffer, globals);
if (end < 0)
PyErr_Print();
if (end)
break;
}
Py_XDECREF(globals);
Py_XDECREF(new_stdin);
Py_XDECREF(new_stdout);
Py_EndInterpreter(tstate);
PyEval_ReleaseLock();
fprintf(output, "Goodbye!\n");
}
static int
run_command(char *buffer, PyObject *globals)
{
PyObject *m, *d, *v;
fprintf(stderr, "run_command: %s", buffer);
if (strchr(buffer, '\n') == NULL)
fprintf(stderr, "\n");
v = PyRun_String(buffer, Py_single_input, globals, globals);
if (v == NULL) {
if (PyErr_Occurred() == PyExc_SystemExit) {
PyErr_Clear();
return 1;
}
PyErr_Print();
return 0;
}
Py_DECREF(v);
return 0;
}
static void
ps(void)
{
char buffer[100];
PyOS_snprintf(buffer, sizeof(buffer),
"ps -l -p %d </dev/null | sed 1d\n", getpid());
system(buffer);
}
#! /usr/bin/env python3
"""A multi-threaded telnet-like server that gives a Python prompt.
This is really a prototype for the same thing in C.
Usage: pysvr.py [port]
For security reasons, it only accepts requests from the current host.
This can still be insecure, but restricts violations from people who
can log in on your machine. Use with caution!
"""
import sys, os, string, getopt, _thread, socket, traceback
PORT = 4000 # Default port
def main():
try:
opts, args = getopt.getopt(sys.argv[1:], "")
if len(args) > 1:
raise getopt.error("Too many arguments.")
except getopt.error as msg:
usage(msg)
for o, a in opts:
pass
if args:
try:
port = string.atoi(args[0])
except ValueError as msg:
usage(msg)
else:
port = PORT
main_thread(port)
def usage(msg=None):
sys.stdout = sys.stderr
if msg:
print(msg)
print("\n", __doc__, end=' ')
sys.exit(2)
def main_thread(port):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(("", port))
sock.listen(5)
print("Listening on port", port, "...")
while 1:
(conn, addr) = sock.accept()
if addr[0] != conn.getsockname()[0]:
conn.close()
print("Refusing connection from non-local host", addr[0], ".")
continue
_thread.start_new_thread(service_thread, (conn, addr))
del conn, addr
def service_thread(conn, addr):
(caddr, cport) = addr
print("Thread %s has connection from %s.\n" % (str(_thread.get_ident()),
caddr), end=' ')
stdin = conn.makefile("r")
stdout = conn.makefile("w", 0)
run_interpreter(stdin, stdout)
print("Thread %s is done.\n" % str(_thread.get_ident()), end=' ')
def run_interpreter(stdin, stdout):
globals = {}
try:
str(sys.ps1)
except:
sys.ps1 = ">>> "
source = ""
while 1:
stdout.write(sys.ps1)
line = stdin.readline()
if line[:2] == '\377\354':
line = ""
if not line and not source:
break
if line[-2:] == '\r\n':
line = line[:-2] + '\n'
source = source + line
try:
code = compile_command(source)
except SyntaxError as err:
source = ""
traceback.print_exception(SyntaxError, err, None, file=stdout)
continue
if not code:
continue
source = ""
try:
run_command(code, stdin, stdout, globals)
except SystemExit as how:
if how:
try:
how = str(how)
except:
how = ""
stdout.write("Exit %s\n" % how)
break
stdout.write("\nGoodbye.\n")
def run_command(code, stdin, stdout, globals):
save = sys.stdin, sys.stdout, sys.stderr
try:
sys.stdout = sys.stderr = stdout
sys.stdin = stdin
try:
exec(code, globals)
except SystemExit as how:
raise SystemExit(how).with_traceback(sys.exc_info()[2])
except:
type, value, tb = sys.exc_info()
if tb: tb = tb.tb_next
traceback.print_exception(type, value, tb)
del tb
finally:
sys.stdin, sys.stdout, sys.stderr = save
from code import compile_command
main()
File Name Archive # Description
-----------------------------------------------------------
MANIFEST 1 This shipping list
README 1
T.py 1
mountclient.py 1
nfsclient.py 1
rpc.py 1
test 1
xdr.py 1
This is a Python interface to Sun RPC, designed and implemented mostly
by reading the Internet RFCs about the subject.
*** NOTE: xdr.py has evolved into the standard module xdrlib.py ***
There are two library modules, xdr.py and rpc.py, and several example
clients: mountclient.py, nfsclient.py, and rnusersclient.py,
implementing the NFS Mount protocol, (part of) the NFS protocol, and
the "rnusers" protocol (used by rusers(1)), respectively. The latter
demonstrates the use of broadcast via the Port mapper's CALLIT
procedure.
There is also a way to create servers in Python.
To test the nfs client, run it from the shell with something like this:
python -c 'import nfsclient; nfsclient.test()' [hostname [filesystemname]]
When called without a filesystemname, it lists the filesystems at the
host; default host is the local machine.
Other clients are tested similarly.
For hostname, use e.g. wuarchive.wustl.edu or gatekeeper.dec.com (two
hosts that are known to export NFS filesystems with little restrictions).
There are now two different RPC compilers:
1) Wim Lewis rpcgen.py found on http://www.omnigroup.com/~wiml/soft/stale-index.html#python.
2) Peter Åstrands rpcgen.py, which is part of "pynfs" (http://www.cendio.se/~peter/pynfs/).
# Simple interface to report execution times of program fragments.
# Call TSTART() to reset the timer, TSTOP(...) to report times.
import sys, os, time
def TSTART():
global t0, t1
u, s, cu, cs = os.times()
t0 = u+cu, s+cs, time.time()
def TSTOP(*label):
global t0, t1
u, s, cu, cs = os.times()
t1 = u+cu, s+cs, time.time()
tt = []
for i in range(3):
tt.append(t1[i] - t0[i])
[u, s, r] = tt
msg = ''
for x in label: msg = msg + (x + ' ')
msg = msg + '%r user, %r sys, %r real\n' % (u, s, r)
sys.stderr.write(msg)
# Mount RPC client -- RFC 1094 (NFS), Appendix A
# This module demonstrates how to write your own RPC client in Python.
# When this example was written, there was no RPC compiler for
# Python. Without such a compiler, you must first create classes
# derived from Packer and Unpacker to handle the data types for the
# server you want to interface to. You then write the client class.
# If you want to support both the TCP and the UDP version of a
# protocol, use multiple inheritance as shown below.
import rpc
from rpc import Packer, Unpacker, TCPClient, UDPClient
# Program number and version for the mount protocol
MOUNTPROG = 100005
MOUNTVERS = 1
# Size of the 'fhandle' opaque structure
FHSIZE = 32
# Packer derived class for Mount protocol clients.
# The only thing we need to pack beyond basic types is an 'fhandle'
class MountPacker(Packer):
def pack_fhandle(self, fhandle):
self.pack_fopaque(FHSIZE, fhandle)
# Unpacker derived class for Mount protocol clients.
# The important types we need to unpack are fhandle, fhstatus,
# mountlist and exportlist; mountstruct, exportstruct and groups are
# used to unpack components of mountlist and exportlist and the
# corresponding functions are passed as function argument to the
# generic unpack_list function.
class MountUnpacker(Unpacker):
def unpack_fhandle(self):
return self.unpack_fopaque(FHSIZE)
def unpack_fhstatus(self):
status = self.unpack_uint()
if status == 0:
fh = self.unpack_fhandle()
else:
fh = None
return status, fh
def unpack_mountlist(self):
return self.unpack_list(self.unpack_mountstruct)
def unpack_mountstruct(self):
hostname = self.unpack_string()
directory = self.unpack_string()
return (hostname, directory)
def unpack_exportlist(self):
return self.unpack_list(self.unpack_exportstruct)
def unpack_exportstruct(self):
filesys = self.unpack_string()
groups = self.unpack_groups()
return (filesys, groups)
def unpack_groups(self):
return self.unpack_list(self.unpack_string)
# These are the procedures specific to the Mount client class.
# Think of this as a derived class of either TCPClient or UDPClient.
class PartialMountClient:
# This method is called by Client.__init__ to initialize
# self.packer and self.unpacker
def addpackers(self):
self.packer = MountPacker()
self.unpacker = MountUnpacker('')
# This method is called by Client.__init__ to bind the socket
# to a particular network interface and port. We use the
# default network interface, but if we're running as root,
# we want to bind to a reserved port
def bindsocket(self):
import os
try:
uid = os.getuid()
except AttributeError:
uid = 1
if uid == 0:
port = rpc.bindresvport(self.sock, '')
# 'port' is not used
else:
self.sock.bind(('', 0))
# This function is called to cough up a suitable
# authentication object for a call to procedure 'proc'.
def mkcred(self):
if self.cred is None:
self.cred = rpc.AUTH_UNIX, rpc.make_auth_unix_default()
return self.cred
# The methods Mnt, Dump etc. each implement one Remote
# Procedure Call. This is done by calling self.make_call()
# with as arguments:
#
# - the procedure number
# - the arguments (or None)
# - the "packer" function for the arguments (or None)
# - the "unpacker" function for the return value (or None)
#
# The packer and unpacker function, if not None, *must* be
# methods of self.packer and self.unpacker, respectively.
# A value of None means that there are no arguments or is no
# return value, respectively.
#
# The return value from make_call() is the return value from
# the remote procedure call, as unpacked by the "unpacker"
# function, or None if the unpacker function is None.
#
# (Even if you expect a result of None, you should still
# return the return value from make_call(), since this may be
# needed by a broadcasting version of the class.)
#
# If the call fails, make_call() raises an exception
# (this includes time-outs and invalid results).
#
# Note that (at least with the UDP protocol) there is no
# guarantee that a call is executed at most once. When you do
# get a reply, you know it has been executed at least once;
# when you don't get a reply, you know nothing.
def Mnt(self, directory):
return self.make_call(1, directory, \
self.packer.pack_string, \
self.unpacker.unpack_fhstatus)
def Dump(self):
return self.make_call(2, None, \
None, self.unpacker.unpack_mountlist)
def Umnt(self, directory):
return self.make_call(3, directory, \
self.packer.pack_string, None)
def Umntall(self):
return self.make_call(4, None, None, None)
def Export(self):
return self.make_call(5, None, \
None, self.unpacker.unpack_exportlist)
# We turn the partial Mount client into a full one for either protocol
# by use of multiple inheritance. (In general, when class C has base
# classes B1...Bn, if x is an instance of class C, methods of x are
# searched first in C, then in B1, then in B2, ..., finally in Bn.)
class TCPMountClient(PartialMountClient, TCPClient):
def __init__(self, host):
TCPClient.__init__(self, host, MOUNTPROG, MOUNTVERS)
class UDPMountClient(PartialMountClient, UDPClient):
def __init__(self, host):
UDPClient.__init__(self, host, MOUNTPROG, MOUNTVERS)
# A little test program for the Mount client. This takes a host as
# command line argument (default the local machine), prints its export
# list, and attempts to mount and unmount each exported files system.
# An optional first argument of -t or -u specifies the protocol to use
# (TCP or UDP), default is UDP.
def test():
import sys
if sys.argv[1:] and sys.argv[1] == '-t':
C = TCPMountClient
del sys.argv[1]
elif sys.argv[1:] and sys.argv[1] == '-u':
C = UDPMountClient
del sys.argv[1]
else:
C = UDPMountClient
if sys.argv[1:]: host = sys.argv[1]
else: host = ''
mcl = C(host)
list = mcl.Export()
for item in list:
print(item)
try:
mcl.Mnt(item[0])
except:
print('Sorry')
continue
mcl.Umnt(item[0])
# NFS RPC client -- RFC 1094
# XXX This is not yet complete.
# XXX Only GETATTR, SETTTR, LOOKUP and READDIR are supported.
# (See mountclient.py for some hints on how to write RPC clients in
# Python in general)
import rpc
from rpc import UDPClient, TCPClient
from mountclient import FHSIZE, MountPacker, MountUnpacker
NFS_PROGRAM = 100003
NFS_VERSION = 2
# enum stat
NFS_OK = 0
# (...many error values...)
# enum ftype
NFNON = 0
NFREG = 1
NFDIR = 2
NFBLK = 3
NFCHR = 4
NFLNK = 5
class NFSPacker(MountPacker):
def pack_sattrargs(self, sa):
file, attributes = sa
self.pack_fhandle(file)
self.pack_sattr(attributes)
def pack_sattr(self, sa):
mode, uid, gid, size, atime, mtime = sa
self.pack_uint(mode)
self.pack_uint(uid)
self.pack_uint(gid)
self.pack_uint(size)
self.pack_timeval(atime)
self.pack_timeval(mtime)
def pack_diropargs(self, da):
dir, name = da
self.pack_fhandle(dir)
self.pack_string(name)
def pack_readdirargs(self, ra):
dir, cookie, count = ra
self.pack_fhandle(dir)
self.pack_uint(cookie)
self.pack_uint(count)
def pack_timeval(self, tv):
secs, usecs = tv
self.pack_uint(secs)
self.pack_uint(usecs)
class NFSUnpacker(MountUnpacker):
def unpack_readdirres(self):
status = self.unpack_enum()
if status == NFS_OK:
entries = self.unpack_list(self.unpack_entry)
eof = self.unpack_bool()
rest = (entries, eof)
else:
rest = None
return (status, rest)
def unpack_entry(self):
fileid = self.unpack_uint()
name = self.unpack_string()
cookie = self.unpack_uint()
return (fileid, name, cookie)
def unpack_diropres(self):
status = self.unpack_enum()
if status == NFS_OK:
fh = self.unpack_fhandle()
fa = self.unpack_fattr()
rest = (fh, fa)
else:
rest = None
return (status, rest)
def unpack_attrstat(self):
status = self.unpack_enum()
if status == NFS_OK:
attributes = self.unpack_fattr()
else:
attributes = None
return status, attributes
def unpack_fattr(self):
type = self.unpack_enum()
mode = self.unpack_uint()
nlink = self.unpack_uint()
uid = self.unpack_uint()
gid = self.unpack_uint()
size = self.unpack_uint()
blocksize = self.unpack_uint()
rdev = self.unpack_uint()
blocks = self.unpack_uint()
fsid = self.unpack_uint()
fileid = self.unpack_uint()
atime = self.unpack_timeval()
mtime = self.unpack_timeval()
ctime = self.unpack_timeval()
return (type, mode, nlink, uid, gid, size, blocksize, \
rdev, blocks, fsid, fileid, atime, mtime, ctime)
def unpack_timeval(self):
secs = self.unpack_uint()
usecs = self.unpack_uint()
return (secs, usecs)
class NFSClient(UDPClient):
def __init__(self, host):
UDPClient.__init__(self, host, NFS_PROGRAM, NFS_VERSION)
def addpackers(self):
self.packer = NFSPacker()
self.unpacker = NFSUnpacker('')
def mkcred(self):
if self.cred is None:
self.cred = rpc.AUTH_UNIX, rpc.make_auth_unix_default()
return self.cred
def Getattr(self, fh):
return self.make_call(1, fh, \
self.packer.pack_fhandle, \
self.unpacker.unpack_attrstat)
def Setattr(self, sa):
return self.make_call(2, sa, \
self.packer.pack_sattrargs, \
self.unpacker.unpack_attrstat)
# Root() is obsolete
def Lookup(self, da):
return self.make_call(4, da, \
self.packer.pack_diropargs, \
self.unpacker.unpack_diropres)
# ...
def Readdir(self, ra):
return self.make_call(16, ra, \
self.packer.pack_readdirargs, \
self.unpacker.unpack_readdirres)
# Shorthand to get the entire contents of a directory
def Listdir(self, dir):
list = []
ra = (dir, 0, 2000)
while 1:
(status, rest) = self.Readdir(ra)
if status != NFS_OK:
break
entries, eof = rest
last_cookie = None
for fileid, name, cookie in entries:
list.append((fileid, name))
last_cookie = cookie
if eof or last_cookie is None:
break
ra = (ra[0], last_cookie, ra[2])
return list
def test():
import sys
if sys.argv[1:]: host = sys.argv[1]
else: host = ''
if sys.argv[2:]: filesys = sys.argv[2]
else: filesys = None
from mountclient import UDPMountClient, TCPMountClient
mcl = TCPMountClient(host)
if filesys is None:
list = mcl.Export()
for item in list:
print(item)
return
sf = mcl.Mnt(filesys)
print(sf)
fh = sf[1]
if fh:
ncl = NFSClient(host)
attrstat = ncl.Getattr(fh)
print(attrstat)
list = ncl.Listdir(fh)
for item in list: print(item)
mcl.Umnt(filesys)
# Remote nusers client interface
import rpc
from rpc import Packer, Unpacker, UDPClient, BroadcastUDPClient
class RnusersPacker(Packer):
def pack_utmp(self, ui):
ut_line, ut_name, ut_host, ut_time = utmp
self.pack_string(ut_line)
self.pack_string(ut_name)
self.pack_string(ut_host)
self.pack_int(ut_time)
def pack_utmpidle(self, ui):
ui_itmp, ui_idle = ui
self.pack_utmp(ui_utmp)
self.pack_uint(ui_idle)
def pack_utmpidlearr(self, list):
self.pack_array(list, self.pack_itmpidle)
class RnusersUnpacker(Unpacker):
def unpack_utmp(self):
ut_line = self.unpack_string()
ut_name = self.unpack_string()
ut_host = self.unpack_string()
ut_time = self.unpack_int()
return ut_line, ut_name, ut_host, ut_time
def unpack_utmpidle(self):
ui_utmp = self.unpack_utmp()
ui_idle = self.unpack_uint()
return ui_utmp, ui_idle
def unpack_utmpidlearr(self):
return self.unpack_array(self.unpack_utmpidle)
class PartialRnusersClient:
def addpackers(self):
self.packer = RnusersPacker()
self.unpacker = RnusersUnpacker('')
def Num(self):
return self.make_call(1, None, None, self.unpacker.unpack_int)
def Names(self):
return self.make_call(2, None, \
None, self.unpacker.unpack_utmpidlearr)
def Allnames(self):
return self.make_call(3, None, \
None, self.unpacker.unpack_utmpidlearr)
class RnusersClient(PartialRnusersClient, UDPClient):
def __init__(self, host):
UDPClient.__init__(self, host, 100002, 2)
class BroadcastRnusersClient(PartialRnusersClient, BroadcastUDPClient):
def __init__(self, bcastaddr):
BroadcastUDPClient.__init__(self, bcastaddr, 100002, 2)
def test():
import sys
if not sys.argv[1:]:
testbcast()
return
else:
host = sys.argv[1]
c = RnusersClient(host)
list = c.Names()
for (line, name, host, time), idle in list:
line = strip0(line)
name = strip0(name)
host = strip0(host)
print("%r %r %r %s %s" % (name, host, line, time, idle))
def testbcast():
c = BroadcastRnusersClient('<broadcast>')
def listit(list, fromaddr):
host, port = fromaddr
print(host + '\t:', end=' ')
for (line, name, host, time), idle in list:
print(strip0(name), end=' ')
print()
c.set_reply_handler(listit)
all = c.Names()
print('Total Count:', len(all))
def strip0(s):
while s and s[-1] == '\0': s = s[:-1]
return s
test()
This diff is collapsed.
: ${PYTHON=python}
: ${SERVER=charon.cwi.nl}
set -xe
$PYTHON -c 'from rpc import test; test()'
$PYTHON -c 'from rpc import test; test()' ${SERVER}
$PYTHON -c 'from rpc import testsvr; testsvr()' &
PID=$!
sleep 2
$PYTHON -c 'from rpc import testclt; testclt()'
kill -2 $PID
$PYTHON -c 'from mountclient import test; test()'
$PYTHON -c 'from mountclient import test; test()' gatekeeper.dec.com
$PYTHON -c 'from nfsclient import test; test()'
$PYTHON -c 'from nfsclient import test; test()' gatekeeper.dec.com
$PYTHON -c 'from nfsclient import test; test()' gatekeeper.dec.com /archive
$PYTHON -c 'from rnusersclient import test; test()' ''
$PYTHON -c 'from rpc import testbcast; testbcast()'
# Implement (a subset of) Sun XDR -- RFC1014.
try:
import struct
except ImportError:
struct = None
Long = type(0)
class Packer:
def __init__(self):
self.reset()
def reset(self):
self.buf = ''
def get_buf(self):
return self.buf
def pack_uint(self, x):
self.buf = self.buf + \
(chr(int(x>>24 & 0xff)) + chr(int(x>>16 & 0xff)) + \
chr(int(x>>8 & 0xff)) + chr(int(x & 0xff)))
if struct and struct.pack('l', 1) == '\0\0\0\1':
def pack_uint(self, x):
if type(x) == Long:
x = int((x + 0x80000000) % 0x100000000 \
- 0x80000000)
self.buf = self.buf + struct.pack('l', x)
pack_int = pack_uint
pack_enum = pack_int
def pack_bool(self, x):
if x: self.buf = self.buf + '\0\0\0\1'
else: self.buf = self.buf + '\0\0\0\0'
def pack_uhyper(self, x):
self.pack_uint(int(x>>32 & 0xffffffff))
self.pack_uint(int(x & 0xffffffff))
pack_hyper = pack_uhyper
def pack_float(self, x):
# XXX
self.buf = self.buf + struct.pack('f', x)
def pack_double(self, x):
# XXX
self.buf = self.buf + struct.pack('d', x)
def pack_fstring(self, n, s):
if n < 0:
raise ValueError('fstring size must be nonnegative')
n = ((n + 3)//4)*4
data = s[:n]
data = data + (n - len(data)) * '\0'
self.buf = self.buf + data
pack_fopaque = pack_fstring
def pack_string(self, s):
n = len(s)
self.pack_uint(n)
self.pack_fstring(n, s)
pack_opaque = pack_string
def pack_list(self, list, pack_item):
for item in list:
self.pack_uint(1)
pack_item(item)
self.pack_uint(0)
def pack_farray(self, n, list, pack_item):
if len(list) != n:
raise ValueError('wrong array size')
for item in list:
pack_item(item)
def pack_array(self, list, pack_item):
n = len(list)
self.pack_uint(n)
self.pack_farray(n, list, pack_item)
class Unpacker:
def __init__(self, data):
self.reset(data)
def reset(self, data):
self.buf = data
self.pos = 0
def done(self):
if self.pos < len(self.buf):
raise RuntimeError('unextracted data remains')
def unpack_uint(self):
i = self.pos
self.pos = j = i+4
data = self.buf[i:j]
if len(data) < 4:
raise EOFError
x = int(ord(data[0]))<<24 | ord(data[1])<<16 | \
ord(data[2])<<8 | ord(data[3])
# Return a Python long only if the value is not representable
# as a nonnegative Python int
if x < 0x80000000: x = int(x)
return x
if struct and struct.unpack('l', '\0\0\0\1') == 1:
def unpack_uint(self):
i = self.pos
self.pos = j = i+4
data = self.buf[i:j]
if len(data) < 4:
raise EOFError
return struct.unpack('l', data)
def unpack_int(self):
x = self.unpack_uint()
if x >= 0x80000000: x = x - 0x100000000
return int(x)
unpack_enum = unpack_int
unpack_bool = unpack_int
def unpack_uhyper(self):
hi = self.unpack_uint()
lo = self.unpack_uint()
return int(hi)<<32 | lo
def unpack_hyper(self):
x = self.unpack_uhyper()
if x >= 0x8000000000000000: x = x - 0x10000000000000000
return x
def unpack_float(self):
# XXX
i = self.pos
self.pos = j = i+4
data = self.buf[i:j]
if len(data) < 4:
raise EOFError
return struct.unpack('f', data)[0]
def unpack_double(self):
# XXX
i = self.pos
self.pos = j = i+8
data = self.buf[i:j]
if len(data) < 8:
raise EOFError
return struct.unpack('d', data)[0]
def unpack_fstring(self, n):
if n < 0:
raise ValueError('fstring size must be nonnegative')
i = self.pos
j = i + (n+3)//4*4
if j > len(self.buf):
raise EOFError
self.pos = j
return self.buf[i:i+n]
unpack_fopaque = unpack_fstring
def unpack_string(self):
n = self.unpack_uint()
return self.unpack_fstring(n)
unpack_opaque = unpack_string
def unpack_list(self, unpack_item):
list = []
while 1:
x = self.unpack_uint()
if x == 0: break
if x != 1:
raise RuntimeError('0 or 1 expected, got %r' % (x, ))
item = unpack_item()
list.append(item)
return list
def unpack_farray(self, n, unpack_item):
list = []
for i in range(n):
list.append(unpack_item())
return list
def unpack_array(self, unpack_item):
n = self.unpack_uint()
return self.unpack_farray(n, unpack_item)
#! /usr/bin/env python3
# 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 as 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 as 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 as 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] & 0o7777)
except os.error as 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 as 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 as 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, end=' ')
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 token in match:
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, end=' ')
return line
if __name__ == "__main__":
main()
#! /usr/bin/env python3
# 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], end=' ')
while 1:
line = mail.readline()
if not line or line == '\n':
break
if line.startswith('Subject: '):
print(repr(line[9:-1]), end=' ')
print()
#! /usr/bin/env python3
# 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 'PRINTER' in os.environ:
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' % next(iter(users))
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
#! /usr/bin/env python3
# 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, 0o777)
if __name__ == "__main__":
main()
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This directory contains some demonstrations of the thread module.
These are mostly "proof of concept" type applications:
Generator.py Generator class implemented with threads.
sync.py Condition variables primitives by Tim Peters.
telnet.py Version of ../sockets/telnet.py using threads.
Coroutine.py Coroutines using threads, by Tim Peters (22 May 94)
fcmp.py Example of above, by Tim
squasher.py Another example of above, also by Tim
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment