diff options
69 files changed, 47 insertions, 7628 deletions
diff --git a/Demo/cgi/README b/Demo/cgi/README deleted file mode 100644 index c0631b6..0000000 --- a/Demo/cgi/README +++ /dev/null @@ -1,10 +0,0 @@ -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 diff --git a/Demo/cgi/cgi0.sh b/Demo/cgi/cgi0.sh deleted file mode 100755 index 5cefcd3..0000000 --- a/Demo/cgi/cgi0.sh +++ /dev/null @@ -1,8 +0,0 @@ -#! /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 diff --git a/Demo/cgi/cgi1.py b/Demo/cgi/cgi1.py deleted file mode 100755 index b4154df..0000000 --- a/Demo/cgi/cgi1.py +++ /dev/null @@ -1,14 +0,0 @@ -#!/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") diff --git a/Demo/cgi/cgi2.py b/Demo/cgi/cgi2.py deleted file mode 100755 index 8aa57b3..0000000 --- a/Demo/cgi/cgi2.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/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() diff --git a/Demo/cgi/cgi3.py b/Demo/cgi/cgi3.py deleted file mode 100755 index de8ef65..0000000 --- a/Demo/cgi/cgi3.py +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env python3 - -"""CGI test 3 (persistent data).""" - -import cgitb; cgitb.enable() - -from wiki import main - -if __name__ == "__main__": - main() diff --git a/Demo/cgi/wiki.py b/Demo/cgi/wiki.py deleted file mode 100644 index 6b97113..0000000 --- a/Demo/cgi/wiki.py +++ /dev/null @@ -1,123 +0,0 @@ -"""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) diff --git a/Demo/comparisons/README b/Demo/comparisons/README deleted file mode 100644 index 111667c..0000000 --- a/Demo/comparisons/README +++ /dev/null @@ -1,60 +0,0 @@ -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 diff --git a/Demo/comparisons/patterns b/Demo/comparisons/patterns deleted file mode 100755 index f4da846..0000000 --- a/Demo/comparisons/patterns +++ /dev/null @@ -1,4 +0,0 @@ -^def -^class -^import -^from diff --git a/Demo/comparisons/regextest.py b/Demo/comparisons/regextest.py deleted file mode 100755 index 547ee0d..0000000 --- a/Demo/comparisons/regextest.py +++ /dev/null @@ -1,47 +0,0 @@ -#! /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() diff --git a/Demo/comparisons/sortingtest.py b/Demo/comparisons/sortingtest.py deleted file mode 100755 index e826e81..0000000 --- a/Demo/comparisons/sortingtest.py +++ /dev/null @@ -1,45 +0,0 @@ -#! /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() diff --git a/Demo/comparisons/systemtest.py b/Demo/comparisons/systemtest.py deleted file mode 100755 index 8276333..0000000 --- a/Demo/comparisons/systemtest.py +++ /dev/null @@ -1,74 +0,0 @@ -#! /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() diff --git a/Demo/curses/ncurses.py b/Demo/curses/ncurses.py deleted file mode 100644 index dedde29..0000000 --- a/Demo/curses/ncurses.py +++ /dev/null @@ -1,273 +0,0 @@ -#!/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) diff --git a/Demo/curses/rain.py b/Demo/curses/rain.py deleted file mode 100644 index 7cabb4f..0000000 --- a/Demo/curses/rain.py +++ /dev/null @@ -1,94 +0,0 @@ -#!/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) diff --git a/Demo/curses/tclock.py b/Demo/curses/tclock.py deleted file mode 100644 index cde0a93..0000000 --- a/Demo/curses/tclock.py +++ /dev/null @@ -1,147 +0,0 @@ -#!/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) diff --git a/Demo/curses/xmas.py b/Demo/curses/xmas.py deleted file mode 100644 index 349b3a8..0000000 --- a/Demo/curses/xmas.py +++ /dev/null @@ -1,906 +0,0 @@ -# asciixmas -# December 1989 Larry Bartz Indianapolis, IN -# -# $Id$ -# -# I'm dreaming of an ascii character-based monochrome Christmas, -# Just like the ones I used to know! -# Via a full duplex communications channel, -# At 9600 bits per second, -# Even though it's kinda slow. -# -# I'm dreaming of an ascii character-based monochrome Christmas, -# With ev'ry C program I write! -# May your screen be merry and bright! -# And may all your Christmases be amber or green, -# (for reduced eyestrain and improved visibility)! -# -# -# Notes on the Python version: -# I used a couple of `try...except curses.error' to get around some functions -# returning ERR. The errors come from using wrapping functions to fill -# windows to the last character cell. The C version doesn't have this problem, -# it simply ignores any return values. -# - -import curses -import sys - -FROMWHO = "Thomas Gellekum <tg@FreeBSD.org>" - -def set_color(win, color): - if curses.has_colors(): - n = color + 1 - curses.init_pair(n, color, my_bg) - win.attroff(curses.A_COLOR) - win.attron(curses.color_pair(n)) - -def unset_color(win): - if curses.has_colors(): - win.attrset(curses.color_pair(0)) - -def look_out(msecs): - curses.napms(msecs) - if stdscr.getch() != -1: - curses.beep() - sys.exit(0) - -def boxit(): - for y in range(0, 20): - stdscr.addch(y, 7, ord('|')) - - for x in range(8, 80): - stdscr.addch(19, x, ord('_')) - - for x in range(0, 80): - stdscr.addch(22, x, ord('_')) - - return - -def seas(): - stdscr.addch(4, 1, ord('S')) - stdscr.addch(6, 1, ord('E')) - stdscr.addch(8, 1, ord('A')) - stdscr.addch(10, 1, ord('S')) - stdscr.addch(12, 1, ord('O')) - stdscr.addch(14, 1, ord('N')) - stdscr.addch(16, 1, ord("'")) - stdscr.addch(18, 1, ord('S')) - - return - -def greet(): - stdscr.addch(3, 5, ord('G')) - stdscr.addch(5, 5, ord('R')) - stdscr.addch(7, 5, ord('E')) - stdscr.addch(9, 5, ord('E')) - stdscr.addch(11, 5, ord('T')) - stdscr.addch(13, 5, ord('I')) - stdscr.addch(15, 5, ord('N')) - stdscr.addch(17, 5, ord('G')) - stdscr.addch(19, 5, ord('S')) - - return - -def fromwho(): - stdscr.addstr(21, 13, FROMWHO) - return - -def tree(): - set_color(treescrn, curses.COLOR_GREEN) - treescrn.addch(1, 11, ord('/')) - treescrn.addch(2, 11, ord('/')) - treescrn.addch(3, 10, ord('/')) - treescrn.addch(4, 9, ord('/')) - treescrn.addch(5, 9, ord('/')) - treescrn.addch(6, 8, ord('/')) - treescrn.addch(7, 7, ord('/')) - treescrn.addch(8, 6, ord('/')) - treescrn.addch(9, 6, ord('/')) - treescrn.addch(10, 5, ord('/')) - treescrn.addch(11, 3, ord('/')) - treescrn.addch(12, 2, ord('/')) - - treescrn.addch(1, 13, ord('\\')) - treescrn.addch(2, 13, ord('\\')) - treescrn.addch(3, 14, ord('\\')) - treescrn.addch(4, 15, ord('\\')) - treescrn.addch(5, 15, ord('\\')) - treescrn.addch(6, 16, ord('\\')) - treescrn.addch(7, 17, ord('\\')) - treescrn.addch(8, 18, ord('\\')) - treescrn.addch(9, 18, ord('\\')) - treescrn.addch(10, 19, ord('\\')) - treescrn.addch(11, 21, ord('\\')) - treescrn.addch(12, 22, ord('\\')) - - treescrn.addch(4, 10, ord('_')) - treescrn.addch(4, 14, ord('_')) - treescrn.addch(8, 7, ord('_')) - treescrn.addch(8, 17, ord('_')) - - treescrn.addstr(13, 0, "//////////// \\\\\\\\\\\\\\\\\\\\\\\\") - - treescrn.addstr(14, 11, "| |") - treescrn.addstr(15, 11, "|_|") - - unset_color(treescrn) - treescrn.refresh() - w_del_msg.refresh() - - return - -def balls(): - treescrn.overlay(treescrn2) - - set_color(treescrn2, curses.COLOR_BLUE) - treescrn2.addch(3, 9, ord('@')) - treescrn2.addch(3, 15, ord('@')) - treescrn2.addch(4, 8, ord('@')) - treescrn2.addch(4, 16, ord('@')) - treescrn2.addch(5, 7, ord('@')) - treescrn2.addch(5, 17, ord('@')) - treescrn2.addch(7, 6, ord('@')) - treescrn2.addch(7, 18, ord('@')) - treescrn2.addch(8, 5, ord('@')) - treescrn2.addch(8, 19, ord('@')) - treescrn2.addch(10, 4, ord('@')) - treescrn2.addch(10, 20, ord('@')) - treescrn2.addch(11, 2, ord('@')) - treescrn2.addch(11, 22, ord('@')) - treescrn2.addch(12, 1, ord('@')) - treescrn2.addch(12, 23, ord('@')) - - unset_color(treescrn2) - treescrn2.refresh() - w_del_msg.refresh() - return - -def star(): - treescrn2.attrset(curses.A_BOLD | curses.A_BLINK) - set_color(treescrn2, curses.COLOR_YELLOW) - - treescrn2.addch(0, 12, ord('*')) - treescrn2.standend() - - unset_color(treescrn2) - treescrn2.refresh() - w_del_msg.refresh() - return - -def strng1(): - treescrn2.attrset(curses.A_BOLD | curses.A_BLINK) - set_color(treescrn2, curses.COLOR_WHITE) - - treescrn2.addch(3, 13, ord('\'')) - treescrn2.addch(3, 12, ord(':')) - treescrn2.addch(3, 11, ord('.')) - - treescrn2.attroff(curses.A_BOLD | curses.A_BLINK) - unset_color(treescrn2) - - treescrn2.refresh() - w_del_msg.refresh() - return - -def strng2(): - treescrn2.attrset(curses.A_BOLD | curses.A_BLINK) - set_color(treescrn2, curses.COLOR_WHITE) - - treescrn2.addch(5, 14, ord('\'')) - treescrn2.addch(5, 13, ord(':')) - treescrn2.addch(5, 12, ord('.')) - treescrn2.addch(5, 11, ord(',')) - treescrn2.addch(6, 10, ord('\'')) - treescrn2.addch(6, 9, ord(':')) - - treescrn2.attroff(curses.A_BOLD | curses.A_BLINK) - unset_color(treescrn2) - - treescrn2.refresh() - w_del_msg.refresh() - return - -def strng3(): - treescrn2.attrset(curses.A_BOLD | curses.A_BLINK) - set_color(treescrn2, curses.COLOR_WHITE) - - treescrn2.addch(7, 16, ord('\'')) - treescrn2.addch(7, 15, ord(':')) - treescrn2.addch(7, 14, ord('.')) - treescrn2.addch(7, 13, ord(',')) - treescrn2.addch(8, 12, ord('\'')) - treescrn2.addch(8, 11, ord(':')) - treescrn2.addch(8, 10, ord('.')) - treescrn2.addch(8, 9, ord(',')) - - treescrn2.attroff(curses.A_BOLD | curses.A_BLINK) - unset_color(treescrn2) - - treescrn2.refresh() - w_del_msg.refresh() - return - -def strng4(): - treescrn2.attrset(curses.A_BOLD | curses.A_BLINK) - set_color(treescrn2, curses.COLOR_WHITE) - - treescrn2.addch(9, 17, ord('\'')) - treescrn2.addch(9, 16, ord(':')) - treescrn2.addch(9, 15, ord('.')) - treescrn2.addch(9, 14, ord(',')) - treescrn2.addch(10, 13, ord('\'')) - treescrn2.addch(10, 12, ord(':')) - treescrn2.addch(10, 11, ord('.')) - treescrn2.addch(10, 10, ord(',')) - treescrn2.addch(11, 9, ord('\'')) - treescrn2.addch(11, 8, ord(':')) - treescrn2.addch(11, 7, ord('.')) - treescrn2.addch(11, 6, ord(',')) - treescrn2.addch(12, 5, ord('\'')) - - treescrn2.attroff(curses.A_BOLD | curses.A_BLINK) - unset_color(treescrn2) - - treescrn2.refresh() - w_del_msg.refresh() - return - -def strng5(): - treescrn2.attrset(curses.A_BOLD | curses.A_BLINK) - set_color(treescrn2, curses.COLOR_WHITE) - - treescrn2.addch(11, 19, ord('\'')) - treescrn2.addch(11, 18, ord(':')) - treescrn2.addch(11, 17, ord('.')) - treescrn2.addch(11, 16, ord(',')) - treescrn2.addch(12, 15, ord('\'')) - treescrn2.addch(12, 14, ord(':')) - treescrn2.addch(12, 13, ord('.')) - treescrn2.addch(12, 12, ord(',')) - - treescrn2.attroff(curses.A_BOLD | curses.A_BLINK) - unset_color(treescrn2) - - # save a fully lit tree - treescrn2.overlay(treescrn) - - treescrn2.refresh() - w_del_msg.refresh() - return - -def blinkit(): - treescrn8.touchwin() - - for cycle in range(5): - if cycle == 0: - treescrn3.overlay(treescrn8) - treescrn8.refresh() - w_del_msg.refresh() - break - elif cycle == 1: - treescrn4.overlay(treescrn8) - treescrn8.refresh() - w_del_msg.refresh() - break - elif cycle == 2: - treescrn5.overlay(treescrn8) - treescrn8.refresh() - w_del_msg.refresh() - break - elif cycle == 3: - treescrn6.overlay(treescrn8) - treescrn8.refresh() - w_del_msg.refresh() - break - elif cycle == 4: - treescrn7.overlay(treescrn8) - treescrn8.refresh() - w_del_msg.refresh() - break - - treescrn8.touchwin() - - # ALL ON - treescrn.overlay(treescrn8) - treescrn8.refresh() - w_del_msg.refresh() - - return - -def deer_step(win, y, x): - win.mvwin(y, x) - win.refresh() - w_del_msg.refresh() - look_out(5) - -def reindeer(): - y_pos = 0 - - for x_pos in range(70, 62, -1): - if x_pos < 66: y_pos = 1 - for looper in range(0, 4): - dotdeer0.addch(y_pos, x_pos, ord('.')) - dotdeer0.refresh() - w_del_msg.refresh() - dotdeer0.erase() - dotdeer0.refresh() - w_del_msg.refresh() - look_out(50) - - y_pos = 2 - - for x_pos in range(x_pos - 1, 50, -1): - for looper in range(0, 4): - if x_pos < 56: - y_pos = 3 - - try: - stardeer0.addch(y_pos, x_pos, ord('*')) - except curses.error: - pass - stardeer0.refresh() - w_del_msg.refresh() - stardeer0.erase() - stardeer0.refresh() - w_del_msg.refresh() - else: - dotdeer0.addch(y_pos, x_pos, ord('*')) - dotdeer0.refresh() - w_del_msg.refresh() - dotdeer0.erase() - dotdeer0.refresh() - w_del_msg.refresh() - - x_pos = 58 - - for y_pos in range(2, 5): - lildeer0.touchwin() - lildeer0.refresh() - w_del_msg.refresh() - - for looper in range(0, 4): - deer_step(lildeer3, y_pos, x_pos) - deer_step(lildeer2, y_pos, x_pos) - deer_step(lildeer1, y_pos, x_pos) - deer_step(lildeer2, y_pos, x_pos) - deer_step(lildeer3, y_pos, x_pos) - - lildeer0.touchwin() - lildeer0.refresh() - w_del_msg.refresh() - - x_pos -= 2 - - x_pos = 35 - - for y_pos in range(5, 10): - - middeer0.touchwin() - middeer0.refresh() - w_del_msg.refresh() - - for looper in range(2): - deer_step(middeer3, y_pos, x_pos) - deer_step(middeer2, y_pos, x_pos) - deer_step(middeer1, y_pos, x_pos) - deer_step(middeer2, y_pos, x_pos) - deer_step(middeer3, y_pos, x_pos) - - middeer0.touchwin() - middeer0.refresh() - w_del_msg.refresh() - - x_pos -= 3 - - look_out(300) - - y_pos = 1 - - for x_pos in range(8, 16): - deer_step(bigdeer4, y_pos, x_pos) - deer_step(bigdeer3, y_pos, x_pos) - deer_step(bigdeer2, y_pos, x_pos) - deer_step(bigdeer1, y_pos, x_pos) - deer_step(bigdeer2, y_pos, x_pos) - deer_step(bigdeer3, y_pos, x_pos) - deer_step(bigdeer4, y_pos, x_pos) - deer_step(bigdeer0, y_pos, x_pos) - - x_pos -= 1 - - for looper in range(0, 6): - deer_step(lookdeer4, y_pos, x_pos) - deer_step(lookdeer3, y_pos, x_pos) - deer_step(lookdeer2, y_pos, x_pos) - deer_step(lookdeer1, y_pos, x_pos) - deer_step(lookdeer2, y_pos, x_pos) - deer_step(lookdeer3, y_pos, x_pos) - deer_step(lookdeer4, y_pos, x_pos) - - deer_step(lookdeer0, y_pos, x_pos) - - for y_pos in range(y_pos, 10): - for looper in range(0, 2): - deer_step(bigdeer4, y_pos, x_pos) - deer_step(bigdeer3, y_pos, x_pos) - deer_step(bigdeer2, y_pos, x_pos) - deer_step(bigdeer1, y_pos, x_pos) - deer_step(bigdeer2, y_pos, x_pos) - deer_step(bigdeer3, y_pos, x_pos) - deer_step(bigdeer4, y_pos, x_pos) - deer_step(bigdeer0, y_pos, x_pos) - - y_pos -= 1 - - deer_step(lookdeer3, y_pos, x_pos) - return - -def main(win): - global stdscr - stdscr = win - - global my_bg, y_pos, x_pos - global treescrn, treescrn2, treescrn3, treescrn4 - global treescrn5, treescrn6, treescrn7, treescrn8 - global dotdeer0, stardeer0 - global lildeer0, lildeer1, lildeer2, lildeer3 - global middeer0, middeer1, middeer2, middeer3 - global bigdeer0, bigdeer1, bigdeer2, bigdeer3, bigdeer4 - global lookdeer0, lookdeer1, lookdeer2, lookdeer3, lookdeer4 - global w_holiday, w_del_msg - - my_bg = curses.COLOR_BLACK - # curses.curs_set(0) - - treescrn = curses.newwin(16, 27, 3, 53) - treescrn2 = curses.newwin(16, 27, 3, 53) - treescrn3 = curses.newwin(16, 27, 3, 53) - treescrn4 = curses.newwin(16, 27, 3, 53) - treescrn5 = curses.newwin(16, 27, 3, 53) - treescrn6 = curses.newwin(16, 27, 3, 53) - treescrn7 = curses.newwin(16, 27, 3, 53) - treescrn8 = curses.newwin(16, 27, 3, 53) - - dotdeer0 = curses.newwin(3, 71, 0, 8) - - stardeer0 = curses.newwin(4, 56, 0, 8) - - lildeer0 = curses.newwin(7, 53, 0, 8) - lildeer1 = curses.newwin(2, 4, 0, 0) - lildeer2 = curses.newwin(2, 4, 0, 0) - lildeer3 = curses.newwin(2, 4, 0, 0) - - middeer0 = curses.newwin(15, 42, 0, 8) - middeer1 = curses.newwin(3, 7, 0, 0) - middeer2 = curses.newwin(3, 7, 0, 0) - middeer3 = curses.newwin(3, 7, 0, 0) - - bigdeer0 = curses.newwin(10, 23, 0, 0) - bigdeer1 = curses.newwin(10, 23, 0, 0) - bigdeer2 = curses.newwin(10, 23, 0, 0) - bigdeer3 = curses.newwin(10, 23, 0, 0) - bigdeer4 = curses.newwin(10, 23, 0, 0) - - lookdeer0 = curses.newwin(10, 25, 0, 0) - lookdeer1 = curses.newwin(10, 25, 0, 0) - lookdeer2 = curses.newwin(10, 25, 0, 0) - lookdeer3 = curses.newwin(10, 25, 0, 0) - lookdeer4 = curses.newwin(10, 25, 0, 0) - - w_holiday = curses.newwin(1, 27, 3, 27) - - w_del_msg = curses.newwin(1, 20, 23, 60) - - try: - w_del_msg.addstr(0, 0, "Hit any key to quit") - except curses.error: - pass - - try: - w_holiday.addstr(0, 0, "H A P P Y H O L I D A Y S") - except curses.error: - pass - - # set up the windows for our various reindeer - lildeer1.addch(0, 0, ord('V')) - lildeer1.addch(1, 0, ord('@')) - lildeer1.addch(1, 1, ord('<')) - lildeer1.addch(1, 2, ord('>')) - try: - lildeer1.addch(1, 3, ord('~')) - except curses.error: - pass - - lildeer2.addch(0, 0, ord('V')) - lildeer2.addch(1, 0, ord('@')) - lildeer2.addch(1, 1, ord('|')) - lildeer2.addch(1, 2, ord('|')) - try: - lildeer2.addch(1, 3, ord('~')) - except curses.error: - pass - - lildeer3.addch(0, 0, ord('V')) - lildeer3.addch(1, 0, ord('@')) - lildeer3.addch(1, 1, ord('>')) - lildeer3.addch(1, 2, ord('<')) - try: - lildeer2.addch(1, 3, ord('~')) # XXX - except curses.error: - pass - - middeer1.addch(0, 2, ord('y')) - middeer1.addch(0, 3, ord('y')) - middeer1.addch(1, 2, ord('0')) - middeer1.addch(1, 3, ord('(')) - middeer1.addch(1, 4, ord('=')) - middeer1.addch(1, 5, ord(')')) - middeer1.addch(1, 6, ord('~')) - middeer1.addch(2, 3, ord('\\')) - middeer1.addch(2, 5, ord('/')) - - middeer2.addch(0, 2, ord('y')) - middeer2.addch(0, 3, ord('y')) - middeer2.addch(1, 2, ord('0')) - middeer2.addch(1, 3, ord('(')) - middeer2.addch(1, 4, ord('=')) - middeer2.addch(1, 5, ord(')')) - middeer2.addch(1, 6, ord('~')) - middeer2.addch(2, 3, ord('|')) - middeer2.addch(2, 5, ord('|')) - - middeer3.addch(0, 2, ord('y')) - middeer3.addch(0, 3, ord('y')) - middeer3.addch(1, 2, ord('0')) - middeer3.addch(1, 3, ord('(')) - middeer3.addch(1, 4, ord('=')) - middeer3.addch(1, 5, ord(')')) - middeer3.addch(1, 6, ord('~')) - middeer3.addch(2, 3, ord('/')) - middeer3.addch(2, 5, ord('\\')) - - bigdeer1.addch(0, 17, ord('\\')) - bigdeer1.addch(0, 18, ord('/')) - bigdeer1.addch(0, 19, ord('\\')) - bigdeer1.addch(0, 20, ord('/')) - bigdeer1.addch(1, 18, ord('\\')) - bigdeer1.addch(1, 20, ord('/')) - bigdeer1.addch(2, 19, ord('|')) - bigdeer1.addch(2, 20, ord('_')) - bigdeer1.addch(3, 18, ord('/')) - bigdeer1.addch(3, 19, ord('^')) - bigdeer1.addch(3, 20, ord('0')) - bigdeer1.addch(3, 21, ord('\\')) - bigdeer1.addch(4, 17, ord('/')) - bigdeer1.addch(4, 18, ord('/')) - bigdeer1.addch(4, 19, ord('\\')) - bigdeer1.addch(4, 22, ord('\\')) - bigdeer1.addstr(5, 7, "^~~~~~~~~// ~~U") - bigdeer1.addstr(6, 7, "( \\_____( /") # )) - bigdeer1.addstr(7, 8, "( ) /") - bigdeer1.addstr(8, 9, "\\\\ /") - bigdeer1.addstr(9, 11, "\\>/>") - - bigdeer2.addch(0, 17, ord('\\')) - bigdeer2.addch(0, 18, ord('/')) - bigdeer2.addch(0, 19, ord('\\')) - bigdeer2.addch(0, 20, ord('/')) - bigdeer2.addch(1, 18, ord('\\')) - bigdeer2.addch(1, 20, ord('/')) - bigdeer2.addch(2, 19, ord('|')) - bigdeer2.addch(2, 20, ord('_')) - bigdeer2.addch(3, 18, ord('/')) - bigdeer2.addch(3, 19, ord('^')) - bigdeer2.addch(3, 20, ord('0')) - bigdeer2.addch(3, 21, ord('\\')) - bigdeer2.addch(4, 17, ord('/')) - bigdeer2.addch(4, 18, ord('/')) - bigdeer2.addch(4, 19, ord('\\')) - bigdeer2.addch(4, 22, ord('\\')) - bigdeer2.addstr(5, 7, "^~~~~~~~~// ~~U") - bigdeer2.addstr(6, 7, "(( )____( /") # )) - bigdeer2.addstr(7, 7, "( / |") - bigdeer2.addstr(8, 8, "\\/ |") - bigdeer2.addstr(9, 9, "|> |>") - - bigdeer3.addch(0, 17, ord('\\')) - bigdeer3.addch(0, 18, ord('/')) - bigdeer3.addch(0, 19, ord('\\')) - bigdeer3.addch(0, 20, ord('/')) - bigdeer3.addch(1, 18, ord('\\')) - bigdeer3.addch(1, 20, ord('/')) - bigdeer3.addch(2, 19, ord('|')) - bigdeer3.addch(2, 20, ord('_')) - bigdeer3.addch(3, 18, ord('/')) - bigdeer3.addch(3, 19, ord('^')) - bigdeer3.addch(3, 20, ord('0')) - bigdeer3.addch(3, 21, ord('\\')) - bigdeer3.addch(4, 17, ord('/')) - bigdeer3.addch(4, 18, ord('/')) - bigdeer3.addch(4, 19, ord('\\')) - bigdeer3.addch(4, 22, ord('\\')) - bigdeer3.addstr(5, 7, "^~~~~~~~~// ~~U") - bigdeer3.addstr(6, 6, "( ()_____( /") # )) - bigdeer3.addstr(7, 6, "/ / /") - bigdeer3.addstr(8, 5, "|/ \\") - bigdeer3.addstr(9, 5, "/> \\>") - - bigdeer4.addch(0, 17, ord('\\')) - bigdeer4.addch(0, 18, ord('/')) - bigdeer4.addch(0, 19, ord('\\')) - bigdeer4.addch(0, 20, ord('/')) - bigdeer4.addch(1, 18, ord('\\')) - bigdeer4.addch(1, 20, ord('/')) - bigdeer4.addch(2, 19, ord('|')) - bigdeer4.addch(2, 20, ord('_')) - bigdeer4.addch(3, 18, ord('/')) - bigdeer4.addch(3, 19, ord('^')) - bigdeer4.addch(3, 20, ord('0')) - bigdeer4.addch(3, 21, ord('\\')) - bigdeer4.addch(4, 17, ord('/')) - bigdeer4.addch(4, 18, ord('/')) - bigdeer4.addch(4, 19, ord('\\')) - bigdeer4.addch(4, 22, ord('\\')) - bigdeer4.addstr(5, 7, "^~~~~~~~~// ~~U") - bigdeer4.addstr(6, 6, "( )______( /") # ) - bigdeer4.addstr(7, 5, "(/ \\") # ) - bigdeer4.addstr(8, 0, "v___= ----^") - - lookdeer1.addstr(0, 16, "\\/ \\/") - lookdeer1.addstr(1, 17, "\\Y/ \\Y/") - lookdeer1.addstr(2, 19, "\\=/") - lookdeer1.addstr(3, 17, "^\\o o/^") - lookdeer1.addstr(4, 17, "//( )") - lookdeer1.addstr(5, 7, "^~~~~~~~~// \\O/") - lookdeer1.addstr(6, 7, "( \\_____( /") # )) - lookdeer1.addstr(7, 8, "( ) /") - lookdeer1.addstr(8, 9, "\\\\ /") - lookdeer1.addstr(9, 11, "\\>/>") - - lookdeer2.addstr(0, 16, "\\/ \\/") - lookdeer2.addstr(1, 17, "\\Y/ \\Y/") - lookdeer2.addstr(2, 19, "\\=/") - lookdeer2.addstr(3, 17, "^\\o o/^") - lookdeer2.addstr(4, 17, "//( )") - lookdeer2.addstr(5, 7, "^~~~~~~~~// \\O/") - lookdeer2.addstr(6, 7, "(( )____( /") # )) - lookdeer2.addstr(7, 7, "( / |") - lookdeer2.addstr(8, 8, "\\/ |") - lookdeer2.addstr(9, 9, "|> |>") - - lookdeer3.addstr(0, 16, "\\/ \\/") - lookdeer3.addstr(1, 17, "\\Y/ \\Y/") - lookdeer3.addstr(2, 19, "\\=/") - lookdeer3.addstr(3, 17, "^\\o o/^") - lookdeer3.addstr(4, 17, "//( )") - lookdeer3.addstr(5, 7, "^~~~~~~~~// \\O/") - lookdeer3.addstr(6, 6, "( ()_____( /") # )) - lookdeer3.addstr(7, 6, "/ / /") - lookdeer3.addstr(8, 5, "|/ \\") - lookdeer3.addstr(9, 5, "/> \\>") - - lookdeer4.addstr(0, 16, "\\/ \\/") - lookdeer4.addstr(1, 17, "\\Y/ \\Y/") - lookdeer4.addstr(2, 19, "\\=/") - lookdeer4.addstr(3, 17, "^\\o o/^") - lookdeer4.addstr(4, 17, "//( )") - lookdeer4.addstr(5, 7, "^~~~~~~~~// \\O/") - lookdeer4.addstr(6, 6, "( )______( /") # ) - lookdeer4.addstr(7, 5, "(/ \\") # ) - lookdeer4.addstr(8, 0, "v___= ----^") - - ############################################### - curses.cbreak() - stdscr.nodelay(1) - - while 1: - stdscr.clear() - treescrn.erase() - w_del_msg.touchwin() - treescrn.touchwin() - treescrn2.erase() - treescrn2.touchwin() - treescrn8.erase() - treescrn8.touchwin() - stdscr.refresh() - look_out(150) - boxit() - stdscr.refresh() - look_out(150) - seas() - stdscr.refresh() - greet() - stdscr.refresh() - look_out(150) - fromwho() - stdscr.refresh() - look_out(150) - tree() - look_out(150) - balls() - look_out(150) - star() - look_out(150) - strng1() - strng2() - strng3() - strng4() - strng5() - - # set up the windows for our blinking trees - # - # treescrn3 - treescrn.overlay(treescrn3) - - # balls - treescrn3.addch(4, 18, ord(' ')) - treescrn3.addch(7, 6, ord(' ')) - treescrn3.addch(8, 19, ord(' ')) - treescrn3.addch(11, 22, ord(' ')) - - # star - treescrn3.addch(0, 12, ord('*')) - - # strng1 - treescrn3.addch(3, 11, ord(' ')) - - # strng2 - treescrn3.addch(5, 13, ord(' ')) - treescrn3.addch(6, 10, ord(' ')) - - # strng3 - treescrn3.addch(7, 16, ord(' ')) - treescrn3.addch(7, 14, ord(' ')) - - # strng4 - treescrn3.addch(10, 13, ord(' ')) - treescrn3.addch(10, 10, ord(' ')) - treescrn3.addch(11, 8, ord(' ')) - - # strng5 - treescrn3.addch(11, 18, ord(' ')) - treescrn3.addch(12, 13, ord(' ')) - - # treescrn4 - treescrn.overlay(treescrn4) - - # balls - treescrn4.addch(3, 9, ord(' ')) - treescrn4.addch(4, 16, ord(' ')) - treescrn4.addch(7, 6, ord(' ')) - treescrn4.addch(8, 19, ord(' ')) - treescrn4.addch(11, 2, ord(' ')) - treescrn4.addch(12, 23, ord(' ')) - - # star - treescrn4.standout() - treescrn4.addch(0, 12, ord('*')) - treescrn4.standend() - - # strng1 - treescrn4.addch(3, 13, ord(' ')) - - # strng2 - - # strng3 - treescrn4.addch(7, 15, ord(' ')) - treescrn4.addch(8, 11, ord(' ')) - - # strng4 - treescrn4.addch(9, 16, ord(' ')) - treescrn4.addch(10, 12, ord(' ')) - treescrn4.addch(11, 8, ord(' ')) - - # strng5 - treescrn4.addch(11, 18, ord(' ')) - treescrn4.addch(12, 14, ord(' ')) - - # treescrn5 - treescrn.overlay(treescrn5) - - # balls - treescrn5.addch(3, 15, ord(' ')) - treescrn5.addch(10, 20, ord(' ')) - treescrn5.addch(12, 1, ord(' ')) - - # star - treescrn5.addch(0, 12, ord(' ')) - - # strng1 - treescrn5.addch(3, 11, ord(' ')) - - # strng2 - treescrn5.addch(5, 12, ord(' ')) - - # strng3 - treescrn5.addch(7, 14, ord(' ')) - treescrn5.addch(8, 10, ord(' ')) - - # strng4 - treescrn5.addch(9, 15, ord(' ')) - treescrn5.addch(10, 11, ord(' ')) - treescrn5.addch(11, 7, ord(' ')) - - # strng5 - treescrn5.addch(11, 17, ord(' ')) - treescrn5.addch(12, 13, ord(' ')) - - # treescrn6 - treescrn.overlay(treescrn6) - - # balls - treescrn6.addch(6, 7, ord(' ')) - treescrn6.addch(7, 18, ord(' ')) - treescrn6.addch(10, 4, ord(' ')) - treescrn6.addch(11, 23, ord(' ')) - - # star - treescrn6.standout() - treescrn6.addch(0, 12, ord('*')) - treescrn6.standend() - - # strng1 - - # strng2 - treescrn6.addch(5, 11, ord(' ')) - - # strng3 - treescrn6.addch(7, 13, ord(' ')) - treescrn6.addch(8, 9, ord(' ')) - - # strng4 - treescrn6.addch(9, 14, ord(' ')) - treescrn6.addch(10, 10, ord(' ')) - treescrn6.addch(11, 6, ord(' ')) - - # strng5 - treescrn6.addch(11, 16, ord(' ')) - treescrn6.addch(12, 12, ord(' ')) - - # treescrn7 - - treescrn.overlay(treescrn7) - - # balls - treescrn7.addch(3, 15, ord(' ')) - treescrn7.addch(6, 7, ord(' ')) - treescrn7.addch(7, 18, ord(' ')) - treescrn7.addch(10, 4, ord(' ')) - treescrn7.addch(11, 22, ord(' ')) - - # star - treescrn7.addch(0, 12, ord('*')) - - # strng1 - treescrn7.addch(3, 12, ord(' ')) - - # strng2 - treescrn7.addch(5, 13, ord(' ')) - treescrn7.addch(6, 9, ord(' ')) - - # strng3 - treescrn7.addch(7, 15, ord(' ')) - treescrn7.addch(8, 11, ord(' ')) - - # strng4 - treescrn7.addch(9, 16, ord(' ')) - treescrn7.addch(10, 12, ord(' ')) - treescrn7.addch(11, 8, ord(' ')) - - # strng5 - treescrn7.addch(11, 18, ord(' ')) - treescrn7.addch(12, 14, ord(' ')) - - look_out(150) - reindeer() - - w_holiday.touchwin() - w_holiday.refresh() - w_del_msg.refresh() - - look_out(500) - for i in range(0, 20): - blinkit() - -curses.wrapper(main) diff --git a/Demo/md5test/README b/Demo/md5test/README deleted file mode 100644 index be7621e..0000000 --- a/Demo/md5test/README +++ /dev/null @@ -1,10 +0,0 @@ -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. diff --git a/Demo/md5test/foo b/Demo/md5test/foo deleted file mode 100755 index f2ba8f8..0000000 --- a/Demo/md5test/foo +++ /dev/null @@ -1 +0,0 @@ -abc
\ No newline at end of file diff --git a/Demo/md5test/md5driver.py b/Demo/md5test/md5driver.py deleted file mode 100644 index 7f561ab..0000000 --- a/Demo/md5test/md5driver.py +++ /dev/null @@ -1,122 +0,0 @@ -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() diff --git a/Demo/parser/FILES b/Demo/parser/FILES deleted file mode 100644 index 1ff59a3..0000000 --- a/Demo/parser/FILES +++ /dev/null @@ -1,6 +0,0 @@ -Demo/parser -Doc/libparser.tex -Lib/AST.py -Lib/symbol.py -Lib/token.py -Modules/parsermodule.c diff --git a/Demo/parser/README b/Demo/parser/README deleted file mode 100644 index a576d33..0000000 --- a/Demo/parser/README +++ /dev/null @@ -1,31 +0,0 @@ -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! diff --git a/Demo/parser/docstring.py b/Demo/parser/docstring.py deleted file mode 100644 index 45a261b..0000000 --- a/Demo/parser/docstring.py +++ /dev/null @@ -1,2 +0,0 @@ -"""Some documentation. -""" diff --git a/Demo/parser/example.py b/Demo/parser/example.py deleted file mode 100644 index c2f0883..0000000 --- a/Demo/parser/example.py +++ /dev/null @@ -1,190 +0,0 @@ -"""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, '') - )) diff --git a/Demo/parser/simple.py b/Demo/parser/simple.py deleted file mode 100644 index 184e2fe..0000000 --- a/Demo/parser/simple.py +++ /dev/null @@ -1 +0,0 @@ -def f(): "maybe a docstring" diff --git a/Demo/parser/source.py b/Demo/parser/source.py deleted file mode 100644 index b900628..0000000 --- a/Demo/parser/source.py +++ /dev/null @@ -1,27 +0,0 @@ -"""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 diff --git a/Demo/parser/test_parser.py b/Demo/parser/test_parser.py deleted file mode 100755 index ffa6630..0000000 --- a/Demo/parser/test_parser.py +++ /dev/null @@ -1,48 +0,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() diff --git a/Demo/parser/texipre.dat b/Demo/parser/texipre.dat deleted file mode 100644 index 8ad03a6..0000000 --- a/Demo/parser/texipre.dat +++ /dev/null @@ -1,100 +0,0 @@ -\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 diff --git a/Demo/pysvr/Makefile b/Demo/pysvr/Makefile deleted file mode 100644 index b4b9f3e..0000000 --- a/Demo/pysvr/Makefile +++ /dev/null @@ -1,57 +0,0 @@ -# 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 diff --git a/Demo/pysvr/README b/Demo/pysvr/README deleted file mode 100644 index 5e64e38..0000000 --- a/Demo/pysvr/README +++ /dev/null @@ -1,9 +0,0 @@ -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! diff --git a/Demo/pysvr/pysvr.c b/Demo/pysvr/pysvr.c deleted file mode 100644 index 706cd2a..0000000 --- a/Demo/pysvr/pysvr.c +++ /dev/null @@ -1,370 +0,0 @@ -/* 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); -} diff --git a/Demo/pysvr/pysvr.py b/Demo/pysvr/pysvr.py deleted file mode 100755 index 578e99c..0000000 --- a/Demo/pysvr/pysvr.py +++ /dev/null @@ -1,124 +0,0 @@ -#! /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() diff --git a/Demo/rpc/MANIFEST b/Demo/rpc/MANIFEST deleted file mode 100644 index e65f3eb..0000000 --- a/Demo/rpc/MANIFEST +++ /dev/null @@ -1,10 +0,0 @@ - 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 diff --git a/Demo/rpc/README b/Demo/rpc/README deleted file mode 100644 index 97948a3..0000000 --- a/Demo/rpc/README +++ /dev/null @@ -1,31 +0,0 @@ -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/). diff --git a/Demo/rpc/T.py b/Demo/rpc/T.py deleted file mode 100644 index 3325507..0000000 --- a/Demo/rpc/T.py +++ /dev/null @@ -1,22 +0,0 @@ -# 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) diff --git a/Demo/rpc/mountclient.py b/Demo/rpc/mountclient.py deleted file mode 100644 index 81797df..0000000 --- a/Demo/rpc/mountclient.py +++ /dev/null @@ -1,202 +0,0 @@ -# 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]) diff --git a/Demo/rpc/nfsclient.py b/Demo/rpc/nfsclient.py deleted file mode 100644 index a291ce0..0000000 --- a/Demo/rpc/nfsclient.py +++ /dev/null @@ -1,201 +0,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) diff --git a/Demo/rpc/rnusersclient.py b/Demo/rpc/rnusersclient.py deleted file mode 100644 index eaabefe..0000000 --- a/Demo/rpc/rnusersclient.py +++ /dev/null @@ -1,98 +0,0 @@ -# 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() diff --git a/Demo/rpc/rpc.py b/Demo/rpc/rpc.py deleted file mode 100644 index 30b3017..0000000 --- a/Demo/rpc/rpc.py +++ /dev/null @@ -1,890 +0,0 @@ -# Sun RPC version 2 -- RFC1057. - -# XXX There should be separate exceptions for the various reasons why -# XXX an RPC can fail, rather than using RuntimeError for everything - -# XXX Need to use class based exceptions rather than string exceptions - -# XXX The UDP version of the protocol resends requests when it does -# XXX not receive a timely reply -- use only for idempotent calls! - -# XXX There is no provision for call timeout on TCP connections - -import xdr -import socket -import os - -RPCVERSION = 2 - -CALL = 0 -REPLY = 1 - -AUTH_NULL = 0 -AUTH_UNIX = 1 -AUTH_SHORT = 2 -AUTH_DES = 3 - -MSG_ACCEPTED = 0 -MSG_DENIED = 1 - -SUCCESS = 0 # RPC executed successfully -PROG_UNAVAIL = 1 # remote hasn't exported program -PROG_MISMATCH = 2 # remote can't support version # -PROC_UNAVAIL = 3 # program can't support procedure -GARBAGE_ARGS = 4 # procedure can't decode params - -RPC_MISMATCH = 0 # RPC version number != 2 -AUTH_ERROR = 1 # remote can't authenticate caller - -AUTH_BADCRED = 1 # bad credentials (seal broken) -AUTH_REJECTEDCRED = 2 # client must begin new session -AUTH_BADVERF = 3 # bad verifier (seal broken) -AUTH_REJECTEDVERF = 4 # verifier expired or replayed -AUTH_TOOWEAK = 5 # rejected for security reasons - - -class Packer(xdr.Packer): - - def pack_auth(self, auth): - flavor, stuff = auth - self.pack_enum(flavor) - self.pack_opaque(stuff) - - def pack_auth_unix(self, stamp, machinename, uid, gid, gids): - self.pack_uint(stamp) - self.pack_string(machinename) - self.pack_uint(uid) - self.pack_uint(gid) - self.pack_uint(len(gids)) - for i in gids: - self.pack_uint(i) - - def pack_callheader(self, xid, prog, vers, proc, cred, verf): - self.pack_uint(xid) - self.pack_enum(CALL) - self.pack_uint(RPCVERSION) - self.pack_uint(prog) - self.pack_uint(vers) - self.pack_uint(proc) - self.pack_auth(cred) - self.pack_auth(verf) - # Caller must add procedure-specific part of call - - def pack_replyheader(self, xid, verf): - self.pack_uint(xid) - self.pack_enum(REPLY) - self.pack_uint(MSG_ACCEPTED) - self.pack_auth(verf) - self.pack_enum(SUCCESS) - # Caller must add procedure-specific part of reply - - -# Exceptions -class BadRPCFormat(Exception): pass -class BadRPCVersion(Exception): pass -class GarbageArgs(Exception): pass - -class Unpacker(xdr.Unpacker): - - def unpack_auth(self): - flavor = self.unpack_enum() - stuff = self.unpack_opaque() - return (flavor, stuff) - - def unpack_callheader(self): - xid = self.unpack_uint() - temp = self.unpack_enum() - if temp != CALL: - raise BadRPCFormat('no CALL but %r' % (temp,)) - temp = self.unpack_uint() - if temp != RPCVERSION: - raise BadRPCVersion('bad RPC version %r' % (temp,)) - prog = self.unpack_uint() - vers = self.unpack_uint() - proc = self.unpack_uint() - cred = self.unpack_auth() - verf = self.unpack_auth() - return xid, prog, vers, proc, cred, verf - # Caller must add procedure-specific part of call - - def unpack_replyheader(self): - xid = self.unpack_uint() - mtype = self.unpack_enum() - if mtype != REPLY: - raise RuntimeError('no REPLY but %r' % (mtype,)) - stat = self.unpack_enum() - if stat == MSG_DENIED: - stat = self.unpack_enum() - if stat == RPC_MISMATCH: - low = self.unpack_uint() - high = self.unpack_uint() - raise RuntimeError('MSG_DENIED: RPC_MISMATCH: %r' % ((low, high),)) - if stat == AUTH_ERROR: - stat = self.unpack_uint() - raise RuntimeError('MSG_DENIED: AUTH_ERROR: %r' % (stat,)) - raise RuntimeError('MSG_DENIED: %r' % (stat,)) - if stat != MSG_ACCEPTED: - raise RuntimeError('Neither MSG_DENIED nor MSG_ACCEPTED: %r' % (stat,)) - verf = self.unpack_auth() - stat = self.unpack_enum() - if stat == PROG_UNAVAIL: - raise RuntimeError('call failed: PROG_UNAVAIL') - if stat == PROG_MISMATCH: - low = self.unpack_uint() - high = self.unpack_uint() - raise RuntimeError('call failed: PROG_MISMATCH: %r' % ((low, high),)) - if stat == PROC_UNAVAIL: - raise RuntimeError('call failed: PROC_UNAVAIL') - if stat == GARBAGE_ARGS: - raise RuntimeError('call failed: GARBAGE_ARGS') - if stat != SUCCESS: - raise RuntimeError('call failed: %r' % (stat,)) - return xid, verf - # Caller must get procedure-specific part of reply - - -# Subroutines to create opaque authentication objects - -def make_auth_null(): - return '' - -def make_auth_unix(seed, host, uid, gid, groups): - p = Packer() - p.pack_auth_unix(seed, host, uid, gid, groups) - return p.get_buf() - -def make_auth_unix_default(): - try: - from os import getuid, getgid - uid = getuid() - gid = getgid() - except ImportError: - uid = gid = 0 - import time - return make_auth_unix(int(time.time()-unix_epoch()), \ - socket.gethostname(), uid, gid, []) - -_unix_epoch = -1 -def unix_epoch(): - """Very painful calculation of when the Unix Epoch is. - - This is defined as the return value of time.time() on Jan 1st, - 1970, 00:00:00 GMT. - - On a Unix system, this should always return 0.0. On a Mac, the - calculations are needed -- and hard because of integer overflow - and other limitations. - - """ - global _unix_epoch - if _unix_epoch >= 0: return _unix_epoch - import time - now = time.time() - localt = time.localtime(now) # (y, m, d, hh, mm, ss, ..., ..., ...) - gmt = time.gmtime(now) - offset = time.mktime(localt) - time.mktime(gmt) - y, m, d, hh, mm, ss = 1970, 1, 1, 0, 0, 0 - offset, ss = divmod(ss + offset, 60) - offset, mm = divmod(mm + offset, 60) - offset, hh = divmod(hh + offset, 24) - d = d + offset - _unix_epoch = time.mktime((y, m, d, hh, mm, ss, 0, 0, 0)) - print("Unix epoch:", time.ctime(_unix_epoch)) - return _unix_epoch - - -# Common base class for clients - -class Client: - - def __init__(self, host, prog, vers, port): - self.host = host - self.prog = prog - self.vers = vers - self.port = port - self.makesocket() # Assigns to self.sock - self.bindsocket() - self.connsocket() - self.lastxid = 0 # XXX should be more random? - self.addpackers() - self.cred = None - self.verf = None - - def close(self): - self.sock.close() - - def makesocket(self): - # This MUST be overridden - raise RuntimeError('makesocket not defined') - - def connsocket(self): - # Override this if you don't want/need a connection - self.sock.connect((self.host, self.port)) - - def bindsocket(self): - # Override this to bind to a different port (e.g. reserved) - self.sock.bind(('', 0)) - - def addpackers(self): - # Override this to use derived classes from Packer/Unpacker - self.packer = Packer() - self.unpacker = Unpacker('') - - def make_call(self, proc, args, pack_func, unpack_func): - # Don't normally override this (but see Broadcast) - if pack_func is None and args is not None: - raise TypeError('non-null args with null pack_func') - self.start_call(proc) - if pack_func: - pack_func(args) - self.do_call() - if unpack_func: - result = unpack_func() - else: - result = None - self.unpacker.done() - return result - - def start_call(self, proc): - # Don't override this - self.lastxid = xid = self.lastxid + 1 - cred = self.mkcred() - verf = self.mkverf() - p = self.packer - p.reset() - p.pack_callheader(xid, self.prog, self.vers, proc, cred, verf) - - def do_call(self): - # This MUST be overridden - raise RuntimeError('do_call not defined') - - def mkcred(self): - # Override this to use more powerful credentials - if self.cred is None: - self.cred = (AUTH_NULL, make_auth_null()) - return self.cred - - def mkverf(self): - # Override this to use a more powerful verifier - if self.verf is None: - self.verf = (AUTH_NULL, make_auth_null()) - return self.verf - - def call_0(self): # Procedure 0 is always like this - return self.make_call(0, None, None, None) - - -# Record-Marking standard support - -def sendfrag(sock, last, frag): - x = len(frag) - if last: x = x | 0x80000000 - header = (chr(int(x>>24 & 0xff)) + chr(int(x>>16 & 0xff)) + \ - chr(int(x>>8 & 0xff)) + chr(int(x & 0xff))) - sock.send(header + frag) - -def sendrecord(sock, record): - sendfrag(sock, 1, record) - -def recvfrag(sock): - header = sock.recv(4) - if len(header) < 4: - raise EOFError - x = int(ord(header[0]))<<24 | ord(header[1])<<16 | \ - ord(header[2])<<8 | ord(header[3]) - last = ((x & 0x80000000) != 0) - n = int(x & 0x7fffffff) - frag = '' - while n > 0: - buf = sock.recv(n) - if not buf: raise EOFError - n = n - len(buf) - frag = frag + buf - return last, frag - -def recvrecord(sock): - record = '' - last = 0 - while not last: - last, frag = recvfrag(sock) - record = record + frag - return record - - -# Try to bind to a reserved port (must be root) - -last_resv_port_tried = None -def bindresvport(sock, host): - global last_resv_port_tried - FIRST, LAST = 600, 1024 # Range of ports to try - if last_resv_port_tried is None: - import os - last_resv_port_tried = FIRST + os.getpid() % (LAST-FIRST) - for i in range(last_resv_port_tried, LAST) + \ - range(FIRST, last_resv_port_tried): - last_resv_port_tried = i - try: - sock.bind((host, i)) - return last_resv_port_tried - except socket.error as e: - (errno, msg) = e - if errno != 114: - raise socket.error(errno, msg) - raise RuntimeError('can\'t assign reserved port') - - -# Client using TCP to a specific port - -class RawTCPClient(Client): - - def makesocket(self): - self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - - def do_call(self): - call = self.packer.get_buf() - sendrecord(self.sock, call) - reply = recvrecord(self.sock) - u = self.unpacker - u.reset(reply) - xid, verf = u.unpack_replyheader() - if xid != self.lastxid: - # Can't really happen since this is TCP... - raise RuntimeError('wrong xid in reply %r instead of %r' % ( - xid, self.lastxid)) - - -# Client using UDP to a specific port - -class RawUDPClient(Client): - - def makesocket(self): - self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - - def do_call(self): - call = self.packer.get_buf() - self.sock.send(call) - try: - from select import select - except ImportError: - print('WARNING: select not found, RPC may hang') - select = None - BUFSIZE = 8192 # Max UDP buffer size - timeout = 1 - count = 5 - while 1: - r, w, x = [self.sock], [], [] - if select: - r, w, x = select(r, w, x, timeout) - if self.sock not in r: - count = count - 1 - if count < 0: raise RuntimeError('timeout') - if timeout < 25: timeout = timeout *2 -## print 'RESEND', timeout, count - self.sock.send(call) - continue - reply = self.sock.recv(BUFSIZE) - u = self.unpacker - u.reset(reply) - xid, verf = u.unpack_replyheader() - if xid != self.lastxid: -## print 'BAD xid' - continue - break - - -# Client using UDP broadcast to a specific port - -class RawBroadcastUDPClient(RawUDPClient): - - def __init__(self, bcastaddr, prog, vers, port): - RawUDPClient.__init__(self, bcastaddr, prog, vers, port) - self.reply_handler = None - self.timeout = 30 - - def connsocket(self): - # Don't connect -- use sendto - self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) - - def set_reply_handler(self, reply_handler): - self.reply_handler = reply_handler - - def set_timeout(self, timeout): - self.timeout = timeout # Use None for infinite timeout - - def make_call(self, proc, args, pack_func, unpack_func): - if pack_func is None and args is not None: - raise TypeError('non-null args with null pack_func') - self.start_call(proc) - if pack_func: - pack_func(args) - call = self.packer.get_buf() - self.sock.sendto(call, (self.host, self.port)) - try: - from select import select - except ImportError: - print('WARNING: select not found, broadcast will hang') - select = None - BUFSIZE = 8192 # Max UDP buffer size (for reply) - replies = [] - if unpack_func is None: - def dummy(): pass - unpack_func = dummy - while 1: - r, w, x = [self.sock], [], [] - if select: - if self.timeout is None: - r, w, x = select(r, w, x) - else: - r, w, x = select(r, w, x, self.timeout) - if self.sock not in r: - break - reply, fromaddr = self.sock.recvfrom(BUFSIZE) - u = self.unpacker - u.reset(reply) - xid, verf = u.unpack_replyheader() - if xid != self.lastxid: -## print 'BAD xid' - continue - reply = unpack_func() - self.unpacker.done() - replies.append((reply, fromaddr)) - if self.reply_handler: - self.reply_handler(reply, fromaddr) - return replies - - -# Port mapper interface - -# Program number, version and (fixed!) port number -PMAP_PROG = 100000 -PMAP_VERS = 2 -PMAP_PORT = 111 - -# Procedure numbers -PMAPPROC_NULL = 0 # (void) -> void -PMAPPROC_SET = 1 # (mapping) -> bool -PMAPPROC_UNSET = 2 # (mapping) -> bool -PMAPPROC_GETPORT = 3 # (mapping) -> unsigned int -PMAPPROC_DUMP = 4 # (void) -> pmaplist -PMAPPROC_CALLIT = 5 # (call_args) -> call_result - -# A mapping is (prog, vers, prot, port) and prot is one of: - -IPPROTO_TCP = 6 -IPPROTO_UDP = 17 - -# A pmaplist is a variable-length list of mappings, as follows: -# either (1, mapping, pmaplist) or (0). - -# A call_args is (prog, vers, proc, args) where args is opaque; -# a call_result is (port, res) where res is opaque. - - -class PortMapperPacker(Packer): - - def pack_mapping(self, mapping): - prog, vers, prot, port = mapping - self.pack_uint(prog) - self.pack_uint(vers) - self.pack_uint(prot) - self.pack_uint(port) - - def pack_pmaplist(self, list): - self.pack_list(list, self.pack_mapping) - - def pack_call_args(self, ca): - prog, vers, proc, args = ca - self.pack_uint(prog) - self.pack_uint(vers) - self.pack_uint(proc) - self.pack_opaque(args) - - -class PortMapperUnpacker(Unpacker): - - def unpack_mapping(self): - prog = self.unpack_uint() - vers = self.unpack_uint() - prot = self.unpack_uint() - port = self.unpack_uint() - return prog, vers, prot, port - - def unpack_pmaplist(self): - return self.unpack_list(self.unpack_mapping) - - def unpack_call_result(self): - port = self.unpack_uint() - res = self.unpack_opaque() - return port, res - - -class PartialPortMapperClient: - - def addpackers(self): - self.packer = PortMapperPacker() - self.unpacker = PortMapperUnpacker('') - - def Set(self, mapping): - return self.make_call(PMAPPROC_SET, mapping, \ - self.packer.pack_mapping, \ - self.unpacker.unpack_uint) - - def Unset(self, mapping): - return self.make_call(PMAPPROC_UNSET, mapping, \ - self.packer.pack_mapping, \ - self.unpacker.unpack_uint) - - def Getport(self, mapping): - return self.make_call(PMAPPROC_GETPORT, mapping, \ - self.packer.pack_mapping, \ - self.unpacker.unpack_uint) - - def Dump(self): - return self.make_call(PMAPPROC_DUMP, None, \ - None, \ - self.unpacker.unpack_pmaplist) - - def Callit(self, ca): - return self.make_call(PMAPPROC_CALLIT, ca, \ - self.packer.pack_call_args, \ - self.unpacker.unpack_call_result) - - -class TCPPortMapperClient(PartialPortMapperClient, RawTCPClient): - - def __init__(self, host): - RawTCPClient.__init__(self, \ - host, PMAP_PROG, PMAP_VERS, PMAP_PORT) - - -class UDPPortMapperClient(PartialPortMapperClient, RawUDPClient): - - def __init__(self, host): - RawUDPClient.__init__(self, \ - host, PMAP_PROG, PMAP_VERS, PMAP_PORT) - - -class BroadcastUDPPortMapperClient(PartialPortMapperClient, \ - RawBroadcastUDPClient): - - def __init__(self, bcastaddr): - RawBroadcastUDPClient.__init__(self, \ - bcastaddr, PMAP_PROG, PMAP_VERS, PMAP_PORT) - - -# Generic clients that find their server through the Port mapper - -class TCPClient(RawTCPClient): - - def __init__(self, host, prog, vers): - pmap = TCPPortMapperClient(host) - port = pmap.Getport((prog, vers, IPPROTO_TCP, 0)) - pmap.close() - if port == 0: - raise RuntimeError('program not registered') - RawTCPClient.__init__(self, host, prog, vers, port) - - -class UDPClient(RawUDPClient): - - def __init__(self, host, prog, vers): - pmap = UDPPortMapperClient(host) - port = pmap.Getport((prog, vers, IPPROTO_UDP, 0)) - pmap.close() - if port == 0: - raise RuntimeError('program not registered') - RawUDPClient.__init__(self, host, prog, vers, port) - - -class BroadcastUDPClient(Client): - - def __init__(self, bcastaddr, prog, vers): - self.pmap = BroadcastUDPPortMapperClient(bcastaddr) - self.pmap.set_reply_handler(self.my_reply_handler) - self.prog = prog - self.vers = vers - self.user_reply_handler = None - self.addpackers() - - def close(self): - self.pmap.close() - - def set_reply_handler(self, reply_handler): - self.user_reply_handler = reply_handler - - def set_timeout(self, timeout): - self.pmap.set_timeout(timeout) - - def my_reply_handler(self, reply, fromaddr): - port, res = reply - self.unpacker.reset(res) - result = self.unpack_func() - self.unpacker.done() - self.replies.append((result, fromaddr)) - if self.user_reply_handler is not None: - self.user_reply_handler(result, fromaddr) - - def make_call(self, proc, args, pack_func, unpack_func): - self.packer.reset() - if pack_func: - pack_func(args) - if unpack_func is None: - def dummy(): pass - self.unpack_func = dummy - else: - self.unpack_func = unpack_func - self.replies = [] - packed_args = self.packer.get_buf() - dummy_replies = self.pmap.Callit( \ - (self.prog, self.vers, proc, packed_args)) - return self.replies - - -# Server classes - -# These are not symmetric to the Client classes -# XXX No attempt is made to provide authorization hooks yet - -class Server: - - def __init__(self, host, prog, vers, port): - self.host = host # Should normally be '' for default interface - self.prog = prog - self.vers = vers - self.port = port # Should normally be 0 for random port - self.makesocket() # Assigns to self.sock and self.prot - self.bindsocket() - self.host, self.port = self.sock.getsockname() - self.addpackers() - - def register(self): - mapping = self.prog, self.vers, self.prot, self.port - p = TCPPortMapperClient(self.host) - if not p.Set(mapping): - raise RuntimeError('register failed') - - def unregister(self): - mapping = self.prog, self.vers, self.prot, self.port - p = TCPPortMapperClient(self.host) - if not p.Unset(mapping): - raise RuntimeError('unregister failed') - - def handle(self, call): - # Don't use unpack_header but parse the header piecewise - # XXX I have no idea if I am using the right error responses! - self.unpacker.reset(call) - self.packer.reset() - xid = self.unpacker.unpack_uint() - self.packer.pack_uint(xid) - temp = self.unpacker.unpack_enum() - if temp != CALL: - return None # Not worthy of a reply - self.packer.pack_uint(REPLY) - temp = self.unpacker.unpack_uint() - if temp != RPCVERSION: - self.packer.pack_uint(MSG_DENIED) - self.packer.pack_uint(RPC_MISMATCH) - self.packer.pack_uint(RPCVERSION) - self.packer.pack_uint(RPCVERSION) - return self.packer.get_buf() - self.packer.pack_uint(MSG_ACCEPTED) - self.packer.pack_auth((AUTH_NULL, make_auth_null())) - prog = self.unpacker.unpack_uint() - if prog != self.prog: - self.packer.pack_uint(PROG_UNAVAIL) - return self.packer.get_buf() - vers = self.unpacker.unpack_uint() - if vers != self.vers: - self.packer.pack_uint(PROG_MISMATCH) - self.packer.pack_uint(self.vers) - self.packer.pack_uint(self.vers) - return self.packer.get_buf() - proc = self.unpacker.unpack_uint() - methname = 'handle_' + repr(proc) - try: - meth = getattr(self, methname) - except AttributeError: - self.packer.pack_uint(PROC_UNAVAIL) - return self.packer.get_buf() - cred = self.unpacker.unpack_auth() - verf = self.unpacker.unpack_auth() - try: - meth() # Unpack args, call turn_around(), pack reply - except (EOFError, GarbageArgs): - # Too few or too many arguments - self.packer.reset() - self.packer.pack_uint(xid) - self.packer.pack_uint(REPLY) - self.packer.pack_uint(MSG_ACCEPTED) - self.packer.pack_auth((AUTH_NULL, make_auth_null())) - self.packer.pack_uint(GARBAGE_ARGS) - return self.packer.get_buf() - - def turn_around(self): - try: - self.unpacker.done() - except RuntimeError: - raise GarbageArgs - self.packer.pack_uint(SUCCESS) - - def handle_0(self): # Handle NULL message - self.turn_around() - - def makesocket(self): - # This MUST be overridden - raise RuntimeError('makesocket not defined') - - def bindsocket(self): - # Override this to bind to a different port (e.g. reserved) - self.sock.bind((self.host, self.port)) - - def addpackers(self): - # Override this to use derived classes from Packer/Unpacker - self.packer = Packer() - self.unpacker = Unpacker('') - - -class TCPServer(Server): - - def makesocket(self): - self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.prot = IPPROTO_TCP - - def loop(self): - self.sock.listen(0) - while 1: - self.session(self.sock.accept()) - - def session(self, connection): - sock, (host, port) = connection - while 1: - try: - call = recvrecord(sock) - except EOFError: - break - except socket.error as msg: - print('socket error:', msg) - break - reply = self.handle(call) - if reply is not None: - sendrecord(sock, reply) - - def forkingloop(self): - # Like loop but uses forksession() - self.sock.listen(0) - while 1: - self.forksession(self.sock.accept()) - - def forksession(self, connection): - # Like session but forks off a subprocess - import os - # Wait for deceased children - try: - while 1: - pid, sts = os.waitpid(0, 1) - except os.error: - pass - pid = None - try: - pid = os.fork() - if pid: # Parent - connection[0].close() - return - # Child - self.session(connection) - finally: - # Make sure we don't fall through in the parent - if pid == 0: - os._exit(0) - - -class UDPServer(Server): - - def makesocket(self): - self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - self.prot = IPPROTO_UDP - - def loop(self): - while 1: - self.session() - - def session(self): - call, host_port = self.sock.recvfrom(8192) - reply = self.handle(call) - if reply is not None: - self.sock.sendto(reply, host_port) - - -# Simple test program -- dump local portmapper status - -def test(): - pmap = UDPPortMapperClient('') - list = pmap.Dump() - list.sort() - for prog, vers, prot, port in list: - print(prog, vers, end=' ') - if prot == IPPROTO_TCP: print('tcp', end=' ') - elif prot == IPPROTO_UDP: print('udp', end=' ') - else: print(prot, end=' ') - print(port) - - -# Test program for broadcast operation -- dump everybody's portmapper status - -def testbcast(): - import sys - if sys.argv[1:]: - bcastaddr = sys.argv[1] - else: - bcastaddr = '<broadcast>' - def rh(reply, fromaddr): - host, port = fromaddr - print(host + '\t' + repr(reply)) - pmap = BroadcastUDPPortMapperClient(bcastaddr) - pmap.set_reply_handler(rh) - pmap.set_timeout(5) - replies = pmap.Getport((100002, 1, IPPROTO_UDP, 0)) - - -# Test program for server, with corresponding client -# On machine A: python -c 'import rpc; rpc.testsvr()' -# On machine B: python -c 'import rpc; rpc.testclt()' A -# (A may be == B) - -def testsvr(): - # Simple test class -- proc 1 doubles its string argument as reply - class S(UDPServer): - def handle_1(self): - arg = self.unpacker.unpack_string() - self.turn_around() - print('RPC function 1 called, arg', repr(arg)) - self.packer.pack_string(arg + arg) - # - s = S('', 0x20000000, 1, 0) - try: - s.unregister() - except RuntimeError as msg: - print('RuntimeError:', msg, '(ignored)') - s.register() - print('Service started...') - try: - s.loop() - finally: - s.unregister() - print('Service interrupted.') - - -def testclt(): - import sys - if sys.argv[1:]: host = sys.argv[1] - else: host = '' - # Client for above server - class C(UDPClient): - def call_1(self, arg): - return self.make_call(1, arg, \ - self.packer.pack_string, \ - self.unpacker.unpack_string) - c = C(host, 0x20000000, 1) - print('making call...') - reply = c.call_1('hello, world, ') - print('call returned', repr(reply)) diff --git a/Demo/rpc/test b/Demo/rpc/test deleted file mode 100755 index ba220f2..0000000 --- a/Demo/rpc/test +++ /dev/null @@ -1,24 +0,0 @@ -: ${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()' diff --git a/Demo/rpc/xdr.py b/Demo/rpc/xdr.py deleted file mode 100644 index 2d5f9c3..0000000 --- a/Demo/rpc/xdr.py +++ /dev/null @@ -1,200 +0,0 @@ -# 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) diff --git a/Demo/scripts/eqfix.py b/Demo/scripts/eqfix.py deleted file mode 100755 index 8d0c8df..0000000 --- a/Demo/scripts/eqfix.py +++ /dev/null @@ -1,198 +0,0 @@ -#! /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() diff --git a/Demo/scripts/from.py b/Demo/scripts/from.py deleted file mode 100755 index c8a9346..0000000 --- a/Demo/scripts/from.py +++ /dev/null @@ -1,35 +0,0 @@ -#! /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() diff --git a/Demo/scripts/lpwatch.py b/Demo/scripts/lpwatch.py deleted file mode 100755 index 01d9fea..0000000 --- a/Demo/scripts/lpwatch.py +++ /dev/null @@ -1,102 +0,0 @@ -#! /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 diff --git a/Demo/scripts/makedir.py b/Demo/scripts/makedir.py deleted file mode 100755 index a14e848..0000000 --- a/Demo/scripts/makedir.py +++ /dev/null @@ -1,21 +0,0 @@ -#! /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() diff --git a/Demo/scripts/mboxconvert.py b/Demo/scripts/mboxconvert.py deleted file mode 100755 index cb3ed89..0000000 --- a/Demo/scripts/mboxconvert.py +++ /dev/null @@ -1,124 +0,0 @@ -#! /usr/bin/env python3 - -# Convert MH directories (1 message per file) or MMDF mailboxes (4x^A -# delimited) to unix mailbox (From ... delimited) on stdout. -# If -f is given, files contain one message per file (e.g. MH messages) - -import rfc822 -import sys -import time -import os -import stat -import getopt -import re - -def main(): - dofile = mmdf - try: - opts, args = getopt.getopt(sys.argv[1:], 'f') - except getopt.error as msg: - sys.stderr.write('%s\n' % msg) - sys.exit(2) - for o, a in opts: - if o == '-f': - dofile = message - if not args: - args = ['-'] - sts = 0 - for arg in args: - if arg == '-' or arg == '': - sts = dofile(sys.stdin) or sts - elif os.path.isdir(arg): - sts = mh(arg) or sts - elif os.path.isfile(arg): - try: - f = open(arg) - except IOError as msg: - sys.stderr.write('%s: %s\n' % (arg, msg)) - sts = 1 - continue - sts = dofile(f) or sts - f.close() - else: - sys.stderr.write('%s: not found\n' % arg) - sts = 1 - if sts: - sys.exit(sts) - -numeric = re.compile('[1-9][0-9]*') - -def mh(dir): - sts = 0 - msgs = os.listdir(dir) - for msg in msgs: - if numeric.match(msg) != len(msg): - continue - fn = os.path.join(dir, msg) - try: - f = open(fn) - except IOError as msg: - sys.stderr.write('%s: %s\n' % (fn, msg)) - sts = 1 - continue - sts = message(f) or sts - return sts - -def mmdf(f): - sts = 0 - while 1: - line = f.readline() - if not line: - break - if line == '\1\1\1\1\n': - sts = message(f, line) or sts - else: - sys.stderr.write( - 'Bad line in MMFD mailbox: %r\n' % (line,)) - return sts - -counter = 0 # for generating unique Message-ID headers - -def message(f, delimiter = ''): - sts = 0 - # Parse RFC822 header - m = rfc822.Message(f) - # Write unix header line - fullname, email = m.getaddr('From') - tt = m.getdate('Date') - if tt: - t = time.mktime(tt) - else: - sys.stderr.write( - 'Unparseable date: %r\n' % (m.get('Date'),)) - t = os.fstat(f.fileno())[stat.ST_MTIME] - print('From', email, time.ctime(t)) - # Copy RFC822 header - for line in m.headers: - print(line, end=' ') - # Invent Message-ID header if none is present - if 'message-id' not in m: - global counter - counter = counter + 1 - msgid = "<%s.%d>" % (hex(t), counter) - sys.stderr.write("Adding Message-ID %s (From %s)\n" % - (msgid, email)) - print("Message-ID:", msgid) - print() - # Copy body - while 1: - line = f.readline() - if line == delimiter: - break - if not line: - sys.stderr.write('Unexpected EOF in message\n') - sts = 1 - break - if line[:5] == 'From ': - line = '>' + line - print(line, end=' ') - # Print trailing newline - print() - return sts - -if __name__ == "__main__": - main() diff --git a/Demo/scripts/morse.py b/Demo/scripts/morse.py deleted file mode 100755 index c2f408f..0000000 --- a/Demo/scripts/morse.py +++ /dev/null @@ -1,128 +0,0 @@ -#! /usr/bin/env python3 - -# DAH should be three DOTs. -# Space between DOTs and DAHs should be one DOT. -# Space between two letters should be one DAH. -# Space between two words should be DOT DAH DAH. - -import sys, math, aifc -from contextlib import closing - -DOT = 30 -DAH = 3 * DOT -OCTAVE = 2 # 1 == 441 Hz, 2 == 882 Hz, ... - -morsetab = { - 'A': '.-', 'a': '.-', - 'B': '-...', 'b': '-...', - 'C': '-.-.', 'c': '-.-.', - 'D': '-..', 'd': '-..', - 'E': '.', 'e': '.', - 'F': '..-.', 'f': '..-.', - 'G': '--.', 'g': '--.', - 'H': '....', 'h': '....', - 'I': '..', 'i': '..', - 'J': '.---', 'j': '.---', - 'K': '-.-', 'k': '-.-', - 'L': '.-..', 'l': '.-..', - 'M': '--', 'm': '--', - 'N': '-.', 'n': '-.', - 'O': '---', 'o': '---', - 'P': '.--.', 'p': '.--.', - 'Q': '--.-', 'q': '--.-', - 'R': '.-.', 'r': '.-.', - 'S': '...', 's': '...', - 'T': '-', 't': '-', - 'U': '..-', 'u': '..-', - 'V': '...-', 'v': '...-', - 'W': '.--', 'w': '.--', - 'X': '-..-', 'x': '-..-', - 'Y': '-.--', 'y': '-.--', - 'Z': '--..', 'z': '--..', - '0': '-----', ',': '--..--', - '1': '.----', '.': '.-.-.-', - '2': '..---', '?': '..--..', - '3': '...--', ';': '-.-.-.', - '4': '....-', ':': '---...', - '5': '.....', "'": '.----.', - '6': '-....', '-': '-....-', - '7': '--...', '/': '-..-.', - '8': '---..', '(': '-.--.-', - '9': '----.', ')': '-.--.-', - ' ': ' ', '_': '..--.-', -} - -nowave = b'\0' * 200 - -# If we play at 44.1 kHz (which we do), then if we produce one sine -# wave in 100 samples, we get a tone of 441 Hz. If we produce two -# sine waves in these 100 samples, we get a tone of 882 Hz. 882 Hz -# appears to be a nice one for playing morse code. -def mkwave(octave): - sinewave = bytearray() - for i in range(100): - val = int(math.sin(math.pi * i * octave / 50.0) * 30000) - sinewave.extend([(val >> 8) & 255, val & 255]) - return bytes(sinewave) - -defaultwave = mkwave(OCTAVE) - -def main(): - import getopt - try: - opts, args = getopt.getopt(sys.argv[1:], 'o:p:') - except getopt.error: - sys.stderr.write('Usage ' + sys.argv[0] + - ' [ -o outfile ] [ -p octave ] [ words ] ...\n') - sys.exit(1) - wave = defaultwave - outfile = 'morse.aifc' - for o, a in opts: - if o == '-o': - outfile = a - if o == '-p': - wave = mkwave(int(a)) - with closing(aifc.open(outfile, 'w')) as fp: - fp.setframerate(44100) - fp.setsampwidth(2) - fp.setnchannels(1) - if args: - source = [' '.join(args)] - else: - source = iter(sys.stdin.readline, '') - for line in source: - mline = morse(line) - play(mline, fp, wave) - -# Convert a string to morse code with \001 between the characters in -# the string. -def morse(line): - res = '' - for c in line: - try: - res += morsetab[c] + '\001' - except KeyError: - pass - return res - -# Play a line of morse code. -def play(line, fp, wave): - for c in line: - if c == '.': - sine(fp, DOT, wave) - elif c == '-': - sine(fp, DAH, wave) - else: # space - pause(fp, DAH + DOT) - pause(fp, DOT) - -def sine(fp, length, wave): - for i in range(length): - fp.writeframesraw(wave) - -def pause(fp, length): - for i in range(length): - fp.writeframesraw(nowave) - -if __name__ == '__main__': - main() diff --git a/Demo/scripts/newslist.doc b/Demo/scripts/newslist.doc deleted file mode 100755 index 87fd9ba..0000000 --- a/Demo/scripts/newslist.doc +++ /dev/null @@ -1,59 +0,0 @@ - NEWSLIST - ======== - A program to assist HTTP browsing of newsgroups - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -WWW browsers such as NCSA Mosaic allow the user to read newsgroup -articles by specifying the group name in a URL eg 'news:comp.answers'. - -To browse through many groups, though, (and there are several thousand -of them) you really need a page or pages containing links to all the -groups. There are some good ones out there, for example, - - http://info.cern.ch/hypertext/DataSources/News/Groups/Overview.html - -is the standard one at CERN, but it only shows the groups available there, -which may be rather different from those available on your machine. - -Newslist is a program which creates a hierarchy of pages for you based -on the groups available from YOUR server. It is written in python - a -splendid interpreted object-oriented language which I suggest you get -right now from the directory /pub/python at ftp.cwi.nl, if you haven't -already got it. - -You should be able to see some sample output by looking at: - http://pelican.cl.cam.ac.uk/newspage/root.html - -Descriptions of newsgroups can be added from a file with one group -per line. eg: - - alt.foo Articles about foo - comp.bar Programming in 'bar' and related languages - -A suitable list detailing most groups can be found at ftp.uu.net in -/uunet-info/newsgroups.gz. - -Make sure you read the information at the beginning of the program source and -configure the variables before running. - -In addition to python, you need: - - An NNTP-based news feed. - A directory in which to put the pages. - -The programming is not very beautiful, but it works! It comes with no -warranty, express or implied, but with the hope that some others may -find it useful. - -Comments, improvements & suggestions welcomed. -Quentin Stafford-Fraser - - ---------------------------------------------------------------------- - Quentin Stafford-Fraser - http://pelican.cl.cam.ac.uk/people/qs101/me.html - - Cambridge University Computer Lab Rank Xerox Cambridge EuroPARC - qs101@cl.cam.ac.uk fraser@europarc.xerox.com - Tel: +44 223 334411 Tel: +44 223 341521 - Fax: +44 223 334679 Fax: +44 223 341510 - ---------------------------------------------------------------------- diff --git a/Demo/scripts/newslist.py b/Demo/scripts/newslist.py deleted file mode 100755 index b345f2ef..0000000 --- a/Demo/scripts/newslist.py +++ /dev/null @@ -1,361 +0,0 @@ -#! /usr/bin/env python3 -####################################################################### -# Newslist $Revision$ -# -# Syntax: -# newslist [ -a ] -# -# This is a program to create a directory full of HTML pages -# which between them contain links to all the newsgroups available -# on your server. -# -# The -a option causes a complete list of all groups to be read from -# the server rather than just the ones which have appeared since last -# execution. This recreates the local list from scratch. Use this on -# the first invocation of the program, and from time to time thereafter. -# When new groups are first created they may appear on your server as -# empty groups. By default, empty groups are ignored by the -a option. -# However, these new groups will not be created again, and so will not -# appear in the server's list of 'new groups' at a later date. Hence it -# won't appear until you do a '-a' after some articles have appeared. -# -# I should really keep a list of ignored empty groups and re-check them -# for articles on every run, but I haven't got around to it yet. -# -# This assumes an NNTP news feed. -# -# Feel free to copy, distribute and modify this code for -# non-commercial use. If you make any useful modifications, let me -# know! -# -# (c) Quentin Stafford-Fraser 1994 -# fraser@europarc.xerox.com qs101@cl.cam.ac.uk -# # -####################################################################### -import sys, nntplib, marshal, time, os - -####################################################################### -# Check these variables before running! # - -# Top directory. -# Filenames which don't start with / are taken as being relative to this. -topdir = os.path.expanduser('~/newspage') - -# The name of your NNTP host -# eg. -# newshost = 'nntp-serv.cl.cam.ac.uk' -# or use following to get the name from the NNTPSERVER environment -# variable: -# newshost = os.environ['NNTPSERVER'] -newshost = 'news.example.com' - -# The filename for a local cache of the newsgroup list -treefile = 'grouptree' - -# The filename for descriptions of newsgroups -# I found a suitable one at ftp.uu.net in /uunet-info/newgroups.gz -# You can set this to '' if you don't wish to use one. -descfile = 'newsgroups' - -# The directory in which HTML pages should be created -# eg. -# pagedir = '/usr/local/lib/html/newspage' -# pagedir = 'pages' -pagedir = topdir - -# The html prefix which will refer to this directory -# eg. -# httppref = '/newspage/', -# or leave blank for relative links between pages: (Recommended) -# httppref = '' -httppref = '' - -# The name of the 'root' news page in this directory. -# A .html suffix will be added. -rootpage = 'root' - -# Set skipempty to 0 if you wish to see links to empty groups as well. -# Only affects the -a option. -skipempty = 1 - -# pagelinkicon can contain html to put an icon after links to -# further pages. This helps to make important links stand out. -# Set to '' if not wanted, or '...' is quite a good one. -pagelinkicon = '... <img src="http://pelican.cl.cam.ac.uk/icons/page.xbm"> ' - -# --------------------------------------------------------------------- -# Less important personal preferences: - -# Sublistsize controls the maximum number of items the will appear as -# an indented sub-list before the whole thing is moved onto a different -# page. The smaller this is, the more pages you will have, but the -# shorter each will be. -sublistsize = 4 - -# That should be all. # -####################################################################### - -for dir in os.curdir, os.environ['HOME']: - rcfile = os.path.join(dir, '.newslistrc.py') - if os.path.exists(rcfile): - print(rcfile) - exec(open(rcfile).read()) - break - -from nntplib import NNTP -from stat import * - -rcsrev = '$Revision$' -rcsrev = ' '.join([s for s in rcsrev.split() if '$' not in s]) -desc = {} - -# Make (possibly) relative filenames into absolute ones -treefile = os.path.join(topdir,treefile) -descfile = os.path.join(topdir,descfile) -page = os.path.join(topdir,pagedir) - -# First the bits for creating trees --------------------------- - -# Addtotree creates/augments a tree from a list of group names -def addtotree(tree, groups): - print('Updating tree...') - for i in groups: - parts = i.split('.') - makeleaf(tree, parts) - -# Makeleaf makes a leaf and the branch leading to it if necessary -def makeleaf(tree,path): - j = path[0] - l = len(path) - - if j not in tree: - tree[j] = {} - if l == 1: - tree[j]['.'] = '.' - if l > 1: - makeleaf(tree[j],path[1:]) - -# Then the bits for outputting trees as pages ---------------- - -# Createpage creates an HTML file named <root>.html containing links -# to those groups beginning with <root>. - -def createpage(root, tree, p): - filename = os.path.join(pagedir, root+'.html') - if root == rootpage: - detail = '' - else: - detail = ' under ' + root - with open(filename, 'w') as f: - # f.write('Content-Type: text/html\n') - f.write('<html>\n<head>\n') - f.write('<title>Newsgroups available%s</title>\n' % detail) - f.write('</head>\n<body>\n') - f.write('<h1>Newsgroups available%s</h1>\n' % detail) - f.write('<a href="%s%s.html">Back to top level</a><p>\n' % - (httppref, rootpage)) - printtree(f, tree, 0, p) - f.write('\n<p>') - f.write("<i>This page automatically created by 'newslist' v. %s." % - rcsrev) - f.write(time.ctime(time.time()) + '</i>\n') - f.write('</body>\n</html>\n') - -# Printtree prints the groups as a bulleted list. Groups with -# more than <sublistsize> subgroups will be put on a separate page. -# Other sets of subgroups are just indented. - -def printtree(f, tree, indent, p): - l = len(tree) - - if l > sublistsize and indent > 0: - # Create a new page and a link to it - f.write('<li><b><a href="%s%s.html">' % (httppref, p[1:])) - f.write(p[1:] + '.*') - f.write('</a></b>%s\n' % pagelinkicon) - createpage(p[1:], tree, p) - return - - kl = sorted(tree.keys()) - - if l > 1: - if indent > 0: - # Create a sub-list - f.write('<li>%s\n<ul>' % p[1:]) - else: - # Create a main list - f.write('<ul>') - indent = indent + 1 - - for i in kl: - if i == '.': - # Output a newsgroup - f.write('<li><a href="news:%s">%s</a> ' % (p[1:], p[1:])) - if p[1:] in desc: - f.write(' <i>%s</i>\n' % desc[p[1:]]) - else: - f.write('\n') - else: - # Output a hierarchy - printtree(f, tree[i], indent, p+'.'+i) - - if l > 1: - f.write('\n</ul>') - -# Reading descriptions file --------------------------------------- - -# This returns a dict mapping group name to its description - -def readdesc(descfile): - global desc - desc = {} - - if descfile == '': - return - - try: - with open(descfile, 'r') as d: - print('Reading descriptions...') - for l in d: - bits = l.split() - try: - grp = bits[0] - dsc = ' '.join(bits[1:]) - if len(dsc) > 1: - desc[grp] = dsc - except IndexError: - pass - except IOError: - print('Failed to open description file ' + descfile) - return - -# Check that ouput directory exists, ------------------------------ -# and offer to create it if not - -def checkopdir(pagedir): - if not os.path.isdir(pagedir): - print('Directory %s does not exist.' % pagedir) - print('Shall I create it for you? (y/n)') - if sys.stdin.readline()[0] == 'y': - try: - os.mkdir(pagedir, 0o777) - except: - print('Sorry - failed!') - sys.exit(1) - else: - print('OK. Exiting.') - sys.exit(1) - -# Read and write current local tree ---------------------------------- - -def readlocallist(treefile): - print('Reading current local group list...') - tree = {} - try: - treetime = time.localtime(os.stat(treefile)[ST_MTIME]) - except: - print('\n*** Failed to open local group cache '+treefile) - print('If this is the first time you have run newslist, then') - print('use the -a option to create it.') - sys.exit(1) - treedate = '%02d%02d%02d' % (treetime[0] % 100, treetime[1], treetime[2]) - try: - with open(treefile, 'rb') as dump: - tree = marshal.load(dump) - except IOError: - print('Cannot open local group list ' + treefile) - return (tree, treedate) - -def writelocallist(treefile, tree): - try: - with open(treefile, 'wb') as dump: - groups = marshal.dump(tree, dump) - print('Saved list to %s\n' % treefile) - except: - print('Sorry - failed to write to local group cache', treefile) - print('Does it (or its directory) have the correct permissions?') - sys.exit(1) - -# Return list of all groups on server ----------------------------- - -def getallgroups(server): - print('Getting list of all groups...') - treedate = '010101' - info = server.list()[1] - groups = [] - print('Processing...') - if skipempty: - print('\nIgnoring following empty groups:') - for i in info: - grpname = i[0].split()[0] - if skipempty and int(i[1]) < int(i[2]): - print(grpname.decode() + ' ', end=' ') - else: - groups.append(grpname.decode()) - print('\n') - if skipempty: - print('(End of empty groups)') - return groups - -# Return list of new groups on server ----------------------------- - -def getnewgroups(server, treedate): - print('Getting list of new groups since start of %s...' % treedate, end=' ') - info = server.newgroups(treedate, '000001')[1] - print('got %d.' % len(info)) - print('Processing...', end=' ') - groups = [] - for i in info: - grpname = i.split()[0] - groups.append(grpname.decode()) - print('Done') - return groups - -# Now the main program -------------------------------------------- - -def main(): - tree = {} - - # Check that the output directory exists - checkopdir(pagedir) - - try: - print('Connecting to %s...' % newshost) - if sys.version[0] == '0': - s = NNTP.init(newshost) - else: - s = NNTP(newshost) - connected = True - except (nntplib.error_temp, nntplib.error_perm) as x: - print('Error connecting to host:', x) - print('I\'ll try to use just the local list.') - connected = False - - # If -a is specified, read the full list of groups from server - if connected and len(sys.argv) > 1 and sys.argv[1] == '-a': - groups = getallgroups(s) - - # Otherwise just read the local file and then add - # groups created since local file last modified. - else: - - (tree, treedate) = readlocallist(treefile) - if connected: - groups = getnewgroups(s, treedate) - - if connected: - addtotree(tree, groups) - writelocallist(treefile,tree) - - # Read group descriptions - readdesc(descfile) - - print('Creating pages...') - createpage(rootpage, tree, '') - print('Done') - -if __name__ == "__main__": - main() - -# That's all folks -###################################################################### diff --git a/Demo/scripts/pi.py b/Demo/scripts/pi.py deleted file mode 100755 index 248f81f..0000000 --- a/Demo/scripts/pi.py +++ /dev/null @@ -1,33 +0,0 @@ -#! /usr/bin/env python3 - -# Print digits of pi forever. -# -# The algorithm, using Python's 'long' integers ("bignums"), works -# with continued fractions, and was conceived by Lambert Meertens. -# -# See also the ABC Programmer's Handbook, by Geurts, Meertens & Pemberton, -# published by Prentice-Hall (UK) Ltd., 1990. - -import sys - -def main(): - k, a, b, a1, b1 = 2, 4, 1, 12, 4 - while True: - # Next approximation - p, q, k = k*k, 2*k+1, k+1 - a, b, a1, b1 = a1, b1, p*a+q*a1, p*b+q*b1 - # Print common digits - d, d1 = a//b, a1//b1 - while d == d1: - output(d) - a, a1 = 10*(a%b), 10*(a1%b1) - d, d1 = a//b, a1//b1 - -def output(d): - # Use write() to avoid spaces between the digits - sys.stdout.write(str(d)) - # Flush so the output is seen immediately - sys.stdout.flush() - -if __name__ == "__main__": - main() diff --git a/Demo/scripts/pp.py b/Demo/scripts/pp.py deleted file mode 100755 index 87b9d8f..0000000 --- a/Demo/scripts/pp.py +++ /dev/null @@ -1,125 +0,0 @@ -#! /usr/bin/env python3 - -# Emulate some Perl command line options. -# Usage: pp [-a] [-c] [-d] [-e scriptline] [-F fieldsep] [-n] [-p] [file] ... -# Where the options mean the following: -# -a : together with -n or -p, splits each line into list F -# -c : check syntax only, do not execute any code -# -d : run the script under the debugger, pdb -# -e scriptline : gives one line of the Python script; may be repeated -# -F fieldsep : sets the field separator for the -a option [not in Perl] -# -n : runs the script for each line of input -# -p : prints the line after the script has run -# When no script lines have been passed, the first file argument -# contains the script. With -n or -p, the remaining arguments are -# read as input to the script, line by line. If a file is '-' -# or missing, standard input is read. - -# XXX To do: -# - add -i extension option (change files in place) -# - make a single loop over the files and lines (changes effect of 'break')? -# - add an option to specify the record separator -# - except for -n/-p, run directly from the file if at all possible - -import sys -import getopt - -FS = '' -SCRIPT = [] -AFLAG = 0 -CFLAG = 0 -DFLAG = 0 -NFLAG = 0 -PFLAG = 0 - -try: - optlist, ARGS = getopt.getopt(sys.argv[1:], 'acde:F:np') -except getopt.error as msg: - sys.stderr.write('%s: %s\n' % (sys.argv[0], msg)) - sys.exit(2) - -for option, optarg in optlist: - if option == '-a': - AFLAG = 1 - elif option == '-c': - CFLAG = 1 - elif option == '-d': - DFLAG = 1 - elif option == '-e': - for line in optarg.split('\n'): - SCRIPT.append(line) - elif option == '-F': - FS = optarg - elif option == '-n': - NFLAG = 1 - PFLAG = 0 - elif option == '-p': - NFLAG = 1 - PFLAG = 1 - else: - print(option, 'not recognized???') - -if not ARGS: ARGS.append('-') - -if not SCRIPT: - if ARGS[0] == '-': - fp = sys.stdin - else: - fp = open(ARGS[0], 'r') - while 1: - line = fp.readline() - if not line: break - SCRIPT.append(line[:-1]) - del fp - del ARGS[0] - if not ARGS: ARGS.append('-') - -if CFLAG: - prologue = ['if 0:'] - epilogue = [] -elif NFLAG: - # Note that it is on purpose that AFLAG and PFLAG are - # tested dynamically each time through the loop - prologue = [ - 'LINECOUNT = 0', - 'for FILE in ARGS:', - ' \tif FILE == \'-\':', - ' \t \tFP = sys.stdin', - ' \telse:', - ' \t \tFP = open(FILE, \'r\')', - ' \tLINENO = 0', - ' \twhile 1:', - ' \t \tLINE = FP.readline()', - ' \t \tif not LINE: break', - ' \t \tLINENO = LINENO + 1', - ' \t \tLINECOUNT = LINECOUNT + 1', - ' \t \tL = LINE[:-1]', - ' \t \taflag = AFLAG', - ' \t \tif aflag:', - ' \t \t \tif FS: F = L.split(FS)', - ' \t \t \telse: F = L.split()' - ] - epilogue = [ - ' \t \tif not PFLAG: continue', - ' \t \tif aflag:', - ' \t \t \tif FS: print(FS.join(F))', - ' \t \t \telse: print(\' \'.join(F))', - ' \t \telse: print(L)', - ] -else: - prologue = ['if 1:'] - epilogue = [] - -# Note that we indent using tabs only, so that any indentation style -# used in 'command' will come out right after re-indentation. - -program = '\n'.join(prologue) + '\n' -for line in SCRIPT: - program += ' \t \t' + line + '\n' -program += '\n'.join(epilogue) + '\n' - -if DFLAG: - import pdb - pdb.run(program) -else: - exec(program) diff --git a/Demo/scripts/primes.py b/Demo/scripts/primes.py deleted file mode 100755 index c994623..0000000 --- a/Demo/scripts/primes.py +++ /dev/null @@ -1,31 +0,0 @@ -#! /usr/bin/env python3 - -# Print prime numbers in a given range - -def primes(min, max): - if max >= 2 >= min: - print(2) - primes = [2] - i = 3 - while i <= max: - for p in primes: - if i % p == 0 or p*p > i: - break - if i % p != 0: - primes.append(i) - if i >= min: - print(i) - i += 2 - -def main(): - import sys - min, max = 2, 0x7fffffff - if sys.argv[1:]: - min = int(sys.argv[1]) - if sys.argv[2:]: - max = int(sys.argv[2]) - primes(min, max) - - -if __name__ == "__main__": - main() diff --git a/Demo/scripts/script.py b/Demo/scripts/script.py deleted file mode 100755 index a815a35..0000000 --- a/Demo/scripts/script.py +++ /dev/null @@ -1,42 +0,0 @@ -#! /usr/bin/env python3 - -# script.py -- Make typescript of terminal session. -# Usage: -# -a Append to typescript. -# -p Use Python as shell. -# Author: Steen Lumholt. - - -import os, time, sys, getopt -import pty - -def read(fd): - data = os.read(fd, 1024) - script.write(data) - return data - -shell = 'sh' -filename = 'typescript' -mode = 'wb' -if 'SHELL' in os.environ: - shell = os.environ['SHELL'] - -try: - opts, args = getopt.getopt(sys.argv[1:], 'ap') -except getopt.error as msg: - print('%s: %s' % (sys.argv[0], msg)) - sys.exit(2) - -for o, a in opts: - if o == '-a': - mode = 'ab' - elif o == '-p': - shell = 'python' - -script = open(filename, mode) - -sys.stdout.write('Script started, file is %s\n' % filename) -script.write(('Script started on %s\n' % time.ctime(time.time())).encode()) -pty.spawn(shell, read) -script.write(('Script done on %s\n' % time.ctime(time.time())).encode()) -sys.stdout.write('Script done, file is %s\n' % filename) diff --git a/Demo/scripts/update.py b/Demo/scripts/update.py deleted file mode 100755 index 49c09d8..0000000 --- a/Demo/scripts/update.py +++ /dev/null @@ -1,92 +0,0 @@ -#! /usr/bin/env python3 - -# Update a bunch of files according to a script. -# The input file contains lines of the form <filename>:<lineno>:<text>, -# meaning that the given line of the given file is to be replaced -# by the given text. This is useful for performing global substitutions -# on grep output: - -import os -import sys -import re - -pat = '^([^: \t\n]+):([1-9][0-9]*):' -prog = re.compile(pat) - -class FileObj: - def __init__(self, filename): - self.filename = filename - self.changed = 0 - try: - self.lines = open(filename, 'r').readlines() - except IOError as msg: - print('*** Can\'t open "%s":' % filename, msg) - self.lines = None - return - print('diffing', self.filename) - - def finish(self): - if not self.changed: - print('no changes to', self.filename) - return - try: - os.rename(self.filename, self.filename + '~') - fp = open(self.filename, 'w') - except (os.error, IOError) as msg: - print('*** Can\'t rewrite "%s":' % self.filename, msg) - return - print('writing', self.filename) - for line in self.lines: - fp.write(line) - fp.close() - self.changed = 0 - - def process(self, lineno, rest): - if self.lines is None: - print('(not processed): %s:%s:%s' % ( - self.filename, lineno, rest), end=' ') - return - i = eval(lineno) - 1 - if not 0 <= i < len(self.lines): - print('*** Line number out of range: %s:%s:%s' % ( - self.filename, lineno, rest), end=' ') - return - if self.lines[i] == rest: - print('(no change): %s:%s:%s' % ( - self.filename, lineno, rest), end=' ') - return - if not self.changed: - self.changed = 1 - print('%sc%s' % (lineno, lineno)) - print('<', self.lines[i], end=' ') - print('---') - self.lines[i] = rest - print('>', self.lines[i], end=' ') - -def main(): - if sys.argv[1:]: - try: - fp = open(sys.argv[1], 'r') - except IOError as msg: - print('Can\'t open "%s":' % sys.argv[1], msg) - sys.exit(1) - else: - fp = sys.stdin - curfile = None - while 1: - line = fp.readline() - if not line: - if curfile: curfile.finish() - break - n = prog.match(line) - if n < 0: - print('Funny line:', line, end=' ') - continue - filename, lineno = prog.group(1, 2) - if not curfile or filename != curfile.filename: - if curfile: curfile.finish() - curfile = FileObj(filename) - curfile.process(lineno, line[n:]) - -if __name__ == "__main__": - main() diff --git a/Demo/threads/Coroutine.py b/Demo/threads/Coroutine.py deleted file mode 100644 index 690fadc..0000000 --- a/Demo/threads/Coroutine.py +++ /dev/null @@ -1,159 +0,0 @@ -# Coroutine implementation using Python threads. -# -# Combines ideas from Guido's Generator module, and from the coroutine -# features of Icon and Simula 67. -# -# To run a collection of functions as coroutines, you need to create -# a Coroutine object to control them: -# co = Coroutine() -# and then 'create' a subsidiary object for each function in the -# collection: -# cof1 = co.create(f1 [, arg1, arg2, ...]) # [] means optional, -# cof2 = co.create(f2 [, arg1, arg2, ...]) #... not list -# cof3 = co.create(f3 [, arg1, arg2, ...]) -# etc. The functions need not be distinct; 'create'ing the same -# function multiple times gives you independent instances of the -# function. -# -# To start the coroutines running, use co.tran on one of the create'd -# functions; e.g., co.tran(cof2). The routine that first executes -# co.tran is called the "main coroutine". It's special in several -# respects: it existed before you created the Coroutine object; if any of -# the create'd coroutines exits (does a return, or suffers an unhandled -# exception), EarlyExit error is raised in the main coroutine; and the -# co.detach() method transfers control directly to the main coroutine -# (you can't use co.tran() for this because the main coroutine doesn't -# have a name ...). -# -# Coroutine objects support these methods: -# -# handle = .create(func [, arg1, arg2, ...]) -# Creates a coroutine for an invocation of func(arg1, arg2, ...), -# and returns a handle ("name") for the coroutine so created. The -# handle can be used as the target in a subsequent .tran(). -# -# .tran(target, data=None) -# Transfer control to the create'd coroutine "target", optionally -# passing it an arbitrary piece of data. To the coroutine A that does -# the .tran, .tran acts like an ordinary function call: another -# coroutine B can .tran back to it later, and if it does A's .tran -# returns the 'data' argument passed to B's tran. E.g., -# -# in coroutine coA in coroutine coC in coroutine coB -# x = co.tran(coC) co.tran(coB) co.tran(coA,12) -# print x # 12 -# -# The data-passing feature is taken from Icon, and greatly cuts -# the need to use global variables for inter-coroutine communication. -# -# .back( data=None ) -# The same as .tran(invoker, data=None), where 'invoker' is the -# coroutine that most recently .tran'ed control to the coroutine -# doing the .back. This is akin to Icon's "&source". -# -# .detach( data=None ) -# The same as .tran(main, data=None), where 'main' is the -# (unnameable!) coroutine that started it all. 'main' has all the -# rights of any other coroutine: upon receiving control, it can -# .tran to an arbitrary coroutine of its choosing, go .back to -# the .detach'er, or .kill the whole thing. -# -# .kill() -# Destroy all the coroutines, and return control to the main -# coroutine. None of the create'ed coroutines can be resumed after a -# .kill(). An EarlyExit exception does a .kill() automatically. It's -# a good idea to .kill() coroutines you're done with, since the -# current implementation consumes a thread for each coroutine that -# may be resumed. - -import _thread as thread -import sync - -class _CoEvent: - def __init__(self, func): - self.f = func - self.e = sync.event() - - def __repr__(self): - if self.f is None: - return 'main coroutine' - else: - return 'coroutine for func ' + self.f.__name__ - - def __hash__(self): - return id(self) - - def __cmp__(x,y): - return cmp(id(x), id(y)) - - def resume(self): - self.e.post() - - def wait(self): - self.e.wait() - self.e.clear() - -class Killed(Exception): pass -class EarlyExit(Exception): pass - -class Coroutine: - def __init__(self): - self.active = self.main = _CoEvent(None) - self.invokedby = {self.main: None} - self.killed = 0 - self.value = None - self.terminated_by = None - - def create(self, func, *args): - me = _CoEvent(func) - self.invokedby[me] = None - thread.start_new_thread(self._start, (me,) + args) - return me - - def _start(self, me, *args): - me.wait() - if not self.killed: - try: - try: - me.f(*args) - except Killed: - pass - finally: - if not self.killed: - self.terminated_by = me - self.kill() - - def kill(self): - if self.killed: - raise TypeError('kill() called on dead coroutines') - self.killed = 1 - for coroutine in self.invokedby.keys(): - coroutine.resume() - - def back(self, data=None): - return self.tran( self.invokedby[self.active], data ) - - def detach(self, data=None): - return self.tran( self.main, data ) - - def tran(self, target, data=None): - if target not in self.invokedby: - raise TypeError('.tran target %r is not an active coroutine' % (target,)) - if self.killed: - raise TypeError('.tran target %r is killed' % (target,)) - self.value = data - me = self.active - self.invokedby[target] = me - self.active = target - target.resume() - - me.wait() - if self.killed: - if self.main is not me: - raise Killed - if self.terminated_by is not None: - raise EarlyExit('%r terminated early' % (self.terminated_by,)) - - return self.value - -# end of module diff --git a/Demo/threads/Generator.py b/Demo/threads/Generator.py deleted file mode 100644 index 3a2963f..0000000 --- a/Demo/threads/Generator.py +++ /dev/null @@ -1,92 +0,0 @@ -# Generator implementation using threads - -import _thread as thread -import sys - -class Killed(Exception): - pass - -class Generator: - # Constructor - def __init__(self, func, args): - self.getlock = thread.allocate_lock() - self.putlock = thread.allocate_lock() - self.getlock.acquire() - self.putlock.acquire() - self.func = func - self.args = args - self.done = 0 - self.killed = 0 - thread.start_new_thread(self._start, ()) - - # Internal routine - def _start(self): - try: - self.putlock.acquire() - if not self.killed: - try: - self.func(self, *self.args) - except Killed: - pass - finally: - if not self.killed: - self.done = 1 - self.getlock.release() - - # Called by producer for each value; raise Killed if no more needed - def put(self, value): - if self.killed: - raise TypeError('put() called on killed generator') - self.value = value - self.getlock.release() # Resume consumer thread - self.putlock.acquire() # Wait for next get() call - if self.killed: - raise Killed - - # Called by producer to get next value; raise EOFError if no more - def get(self): - if self.killed: - raise TypeError('get() called on killed generator') - self.putlock.release() # Resume producer thread - self.getlock.acquire() # Wait for value to appear - if self.done: - raise EOFError # Say there are no more values - return self.value - - # Called by consumer if no more values wanted - def kill(self): - if self.killed: - raise TypeError('kill() called on killed generator') - self.killed = 1 - self.putlock.release() - - # Clone constructor - def clone(self): - return Generator(self.func, self.args) - -def pi(g): - k, a, b, a1, b1 = 2, 4, 1, 12, 4 - while 1: - # Next approximation - p, q, k = k*k, 2*k+1, k+1 - a, b, a1, b1 = a1, b1, p*a+q*a1, p*b+q*b1 - # Print common digits - d, d1 = a//b, a1//b1 - while d == d1: - g.put(int(d)) - a, a1 = 10*(a%b), 10*(a1%b1) - d, d1 = a//b, a1//b1 - -def test(): - g = Generator(pi, ()) - g.kill() - g = Generator(pi, ()) - for i in range(10): print(g.get(), end=' ') - print() - h = g.clone() - g.kill() - while 1: - print(h.get(), end=' ') - sys.stdout.flush() - -test() diff --git a/Demo/threads/README b/Demo/threads/README deleted file mode 100644 index a379521..0000000 --- a/Demo/threads/README +++ /dev/null @@ -1,11 +0,0 @@ -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 diff --git a/Demo/threads/fcmp.py b/Demo/threads/fcmp.py deleted file mode 100644 index bc2e3ed..0000000 --- a/Demo/threads/fcmp.py +++ /dev/null @@ -1,64 +0,0 @@ -# Coroutine example: controlling multiple instances of a single function - -from Coroutine import * - -# fringe visits a nested list in inorder, and detaches for each non-list -# element; raises EarlyExit after the list is exhausted -def fringe(co, list): - for x in list: - if type(x) is type([]): - fringe(co, x) - else: - co.back(x) - -def printinorder(list): - co = Coroutine() - f = co.create(fringe, co, list) - try: - while 1: - print(co.tran(f), end=' ') - except EarlyExit: - pass - print() - -printinorder([1,2,3]) # 1 2 3 -printinorder([[[[1,[2]]],3]]) # ditto -x = [0, 1, [2, [3]], [4,5], [[[6]]] ] -printinorder(x) # 0 1 2 3 4 5 6 - -# fcmp lexicographically compares the fringes of two nested lists -def fcmp(l1, l2): - co1 = Coroutine(); f1 = co1.create(fringe, co1, l1) - co2 = Coroutine(); f2 = co2.create(fringe, co2, l2) - while 1: - try: - v1 = co1.tran(f1) - except EarlyExit: - try: - v2 = co2.tran(f2) - except EarlyExit: - return 0 - co2.kill() - return -1 - try: - v2 = co2.tran(f2) - except EarlyExit: - co1.kill() - return 1 - if v1 != v2: - co1.kill(); co2.kill() - return cmp(v1,v2) - -print(fcmp(range(7), x)) # 0; fringes are equal -print(fcmp(range(6), x)) # -1; 1st list ends early -print(fcmp(x, range(6))) # 1; 2nd list ends early -print(fcmp(range(8), x)) # 1; 2nd list ends early -print(fcmp(x, range(8))) # -1; 1st list ends early -print(fcmp([1,[[2],8]], - [[[1],2],8])) # 0 -print(fcmp([1,[[3],8]], - [[[1],2],8])) # 1 -print(fcmp([1,[[2],8]], - [[[1],2],9])) # -1 - -# end of example diff --git a/Demo/threads/find.py b/Demo/threads/find.py deleted file mode 100644 index 2b4ef7d..0000000 --- a/Demo/threads/find.py +++ /dev/null @@ -1,154 +0,0 @@ -# A parallelized "find(1)" using the thread module. - -# This demonstrates the use of a work queue and worker threads. -# It really does do more stats/sec when using multiple threads, -# although the improvement is only about 20-30 percent. -# (That was 8 years ago. In 2002, on Linux, I can't measure -# a speedup. :-( ) - -# I'm too lazy to write a command line parser for the full find(1) -# command line syntax, so the predicate it searches for is wired-in, -# see function selector() below. (It currently searches for files with -# world write permission.) - -# Usage: parfind.py [-w nworkers] [directory] ... -# Default nworkers is 4 - - -import sys -import getopt -import time -import os -from stat import * -import _thread as thread - - -# Work queue class. Usage: -# wq = WorkQ() -# wq.addwork(func, (arg1, arg2, ...)) # one or more calls -# wq.run(nworkers) -# The work is done when wq.run() completes. -# The function calls executed by the workers may add more work. -# Don't use keyboard interrupts! - -class WorkQ: - - # Invariants: - - # - busy and work are only modified when mutex is locked - # - len(work) is the number of jobs ready to be taken - # - busy is the number of jobs being done - # - todo is locked iff there is no work and somebody is busy - - def __init__(self): - self.mutex = thread.allocate() - self.todo = thread.allocate() - self.todo.acquire() - self.work = [] - self.busy = 0 - - def addwork(self, func, args): - job = (func, args) - self.mutex.acquire() - self.work.append(job) - self.mutex.release() - if len(self.work) == 1: - self.todo.release() - - def _getwork(self): - self.todo.acquire() - self.mutex.acquire() - if self.busy == 0 and len(self.work) == 0: - self.mutex.release() - self.todo.release() - return None - job = self.work[0] - del self.work[0] - self.busy = self.busy + 1 - self.mutex.release() - if len(self.work) > 0: - self.todo.release() - return job - - def _donework(self): - self.mutex.acquire() - self.busy = self.busy - 1 - if self.busy == 0 and len(self.work) == 0: - self.todo.release() - self.mutex.release() - - def _worker(self): - time.sleep(0.00001) # Let other threads run - while 1: - job = self._getwork() - if not job: - break - func, args = job - func(*args) - self._donework() - - def run(self, nworkers): - if not self.work: - return # Nothing to do - for i in range(nworkers-1): - thread.start_new(self._worker, ()) - self._worker() - self.todo.acquire() - - -# Main program - -def main(): - nworkers = 4 - opts, args = getopt.getopt(sys.argv[1:], '-w:') - for opt, arg in opts: - if opt == '-w': - nworkers = int(arg) - if not args: - args = [os.curdir] - - wq = WorkQ() - for dir in args: - wq.addwork(find, (dir, selector, wq)) - - t1 = time.time() - wq.run(nworkers) - t2 = time.time() - - sys.stderr.write('Total time %r sec.\n' % (t2-t1)) - - -# The predicate -- defines what files we look for. -# Feel free to change this to suit your purpose - -def selector(dir, name, fullname, stat): - # Look for world writable files that are not symlinks - return (stat[ST_MODE] & 0o002) != 0 and not S_ISLNK(stat[ST_MODE]) - - -# The find procedure -- calls wq.addwork() for subdirectories - -def find(dir, pred, wq): - try: - names = os.listdir(dir) - except os.error as msg: - print(repr(dir), ':', msg) - return - for name in names: - if name not in (os.curdir, os.pardir): - fullname = os.path.join(dir, name) - try: - stat = os.lstat(fullname) - except os.error as msg: - print(repr(fullname), ':', msg) - continue - if pred(dir, name, fullname, stat): - print(fullname) - if S_ISDIR(stat[ST_MODE]): - if not os.path.ismount(fullname): - wq.addwork(find, (fullname, pred, wq)) - - -# Call the main program - -main() diff --git a/Demo/threads/squasher.py b/Demo/threads/squasher.py deleted file mode 100644 index 35b1b1d..0000000 --- a/Demo/threads/squasher.py +++ /dev/null @@ -1,105 +0,0 @@ -# Coroutine example: general coroutine transfers -# -# The program is a variation of a Simula 67 program due to Dahl & Hoare, -# (Dahl/Dijkstra/Hoare, Structured Programming; Academic Press, 1972) -# who in turn credit the original example to Conway. -# -# We have a number of input lines, terminated by a 0 byte. The problem -# is to squash them together into output lines containing 72 characters -# each. A semicolon must be added between input lines. Runs of blanks -# and tabs in input lines must be squashed into single blanks. -# Occurrences of "**" in input lines must be replaced by "^". -# -# Here's a test case: - -test = """\ - d = sqrt(b**2 - 4*a*c) -twoa = 2*a - L = -b/twoa - R = d/twoa - A1 = L + R - A2 = L - R\0 -""" - -# The program should print: - -# d = sqrt(b^2 - 4*a*c);twoa = 2*a; L = -b/twoa; R = d/twoa; A1 = L + R; -#A2 = L - R -#done - -# getline: delivers the next input line to its invoker -# disassembler: grabs input lines from getline, and delivers them one -# character at a time to squasher, also inserting a semicolon into -# the stream between lines -# squasher: grabs characters from disassembler and passes them on to -# assembler, first replacing "**" with "^" and squashing runs of -# whitespace -# assembler: grabs characters from squasher and packs them into lines -# with 72 character each, delivering each such line to putline; -# when it sees a null byte, passes the last line to putline and -# then kills all the coroutines -# putline: grabs lines from assembler, and just prints them - -from Coroutine import * - -def getline(text): - for line in string.splitfields(text, '\n'): - co.tran(codisassembler, line) - -def disassembler(): - while 1: - card = co.tran(cogetline) - for i in range(len(card)): - co.tran(cosquasher, card[i]) - co.tran(cosquasher, ';') - -def squasher(): - while 1: - ch = co.tran(codisassembler) - if ch == '*': - ch2 = co.tran(codisassembler) - if ch2 == '*': - ch = '^' - else: - co.tran(coassembler, ch) - ch = ch2 - if ch in ' \t': - while 1: - ch2 = co.tran(codisassembler) - if ch2 not in ' \t': - break - co.tran(coassembler, ' ') - ch = ch2 - co.tran(coassembler, ch) - -def assembler(): - line = '' - while 1: - ch = co.tran(cosquasher) - if ch == '\0': - break - if len(line) == 72: - co.tran(coputline, line) - line = '' - line = line + ch - line = line + ' ' * (72 - len(line)) - co.tran(coputline, line) - co.kill() - -def putline(): - while 1: - line = co.tran(coassembler) - print(line) - -import string -co = Coroutine() -cogetline = co.create(getline, test) -coputline = co.create(putline) -coassembler = co.create(assembler) -codisassembler = co.create(disassembler) -cosquasher = co.create(squasher) - -co.tran(coputline) -print('done') - -# end of example diff --git a/Demo/threads/sync.py b/Demo/threads/sync.py deleted file mode 100644 index 90fff2e..0000000 --- a/Demo/threads/sync.py +++ /dev/null @@ -1,599 +0,0 @@ -# Defines classes that provide synchronization objects. Note that use of -# this module requires that your Python support threads. -# -# condition(lock=None) # a POSIX-like condition-variable object -# barrier(n) # an n-thread barrier -# event() # an event object -# semaphore(n=1) # a semaphore object, with initial count n -# mrsw() # a multiple-reader single-writer lock -# -# CONDITIONS -# -# A condition object is created via -# import this_module -# your_condition_object = this_module.condition(lock=None) -# -# As explained below, a condition object has a lock associated with it, -# used in the protocol to protect condition data. You can specify a -# lock to use in the constructor, else the constructor will allocate -# an anonymous lock for you. Specifying a lock explicitly can be useful -# when more than one condition keys off the same set of shared data. -# -# Methods: -# .acquire() -# acquire the lock associated with the condition -# .release() -# release the lock associated with the condition -# .wait() -# block the thread until such time as some other thread does a -# .signal or .broadcast on the same condition, and release the -# lock associated with the condition. The lock associated with -# the condition MUST be in the acquired state at the time -# .wait is invoked. -# .signal() -# wake up exactly one thread (if any) that previously did a .wait -# on the condition; that thread will awaken with the lock associated -# with the condition in the acquired state. If no threads are -# .wait'ing, this is a nop. If more than one thread is .wait'ing on -# the condition, any of them may be awakened. -# .broadcast() -# wake up all threads (if any) that are .wait'ing on the condition; -# the threads are woken up serially, each with the lock in the -# acquired state, so should .release() as soon as possible. If no -# threads are .wait'ing, this is a nop. -# -# Note that if a thread does a .wait *while* a signal/broadcast is -# in progress, it's guaranteeed to block until a subsequent -# signal/broadcast. -# -# Secret feature: `broadcast' actually takes an integer argument, -# and will wake up exactly that many waiting threads (or the total -# number waiting, if that's less). Use of this is dubious, though, -# and probably won't be supported if this form of condition is -# reimplemented in C. -# -# DIFFERENCES FROM POSIX -# -# + A separate mutex is not needed to guard condition data. Instead, a -# condition object can (must) be .acquire'ed and .release'ed directly. -# This eliminates a common error in using POSIX conditions. -# -# + Because of implementation difficulties, a POSIX `signal' wakes up -# _at least_ one .wait'ing thread. Race conditions make it difficult -# to stop that. This implementation guarantees to wake up only one, -# but you probably shouldn't rely on that. -# -# PROTOCOL -# -# Condition objects are used to block threads until "some condition" is -# true. E.g., a thread may wish to wait until a producer pumps out data -# for it to consume, or a server may wish to wait until someone requests -# its services, or perhaps a whole bunch of threads want to wait until a -# preceding pass over the data is complete. Early models for conditions -# relied on some other thread figuring out when a blocked thread's -# condition was true, and made the other thread responsible both for -# waking up the blocked thread and guaranteeing that it woke up with all -# data in a correct state. This proved to be very delicate in practice, -# and gave conditions a bad name in some circles. -# -# The POSIX model addresses these problems by making a thread responsible -# for ensuring that its own state is correct when it wakes, and relies -# on a rigid protocol to make this easy; so long as you stick to the -# protocol, POSIX conditions are easy to "get right": -# -# A) The thread that's waiting for some arbitrarily-complex condition -# (ACC) to become true does: -# -# condition.acquire() -# while not (code to evaluate the ACC): -# condition.wait() -# # That blocks the thread, *and* releases the lock. When a -# # condition.signal() happens, it will wake up some thread that -# # did a .wait, *and* acquire the lock again before .wait -# # returns. -# # -# # Because the lock is acquired at this point, the state used -# # in evaluating the ACC is frozen, so it's safe to go back & -# # reevaluate the ACC. -# -# # At this point, ACC is true, and the thread has the condition -# # locked. -# # So code here can safely muck with the shared state that -# # went into evaluating the ACC -- if it wants to. -# # When done mucking with the shared state, do -# condition.release() -# -# B) Threads that are mucking with shared state that may affect the -# ACC do: -# -# condition.acquire() -# # muck with shared state -# condition.release() -# if it's possible that ACC is true now: -# condition.signal() # or .broadcast() -# -# Note: You may prefer to put the "if" clause before the release(). -# That's fine, but do note that anyone waiting on the signal will -# stay blocked until the release() is done (since acquiring the -# condition is part of what .wait() does before it returns). -# -# TRICK OF THE TRADE -# -# With simpler forms of conditions, it can be impossible to know when -# a thread that's supposed to do a .wait has actually done it. But -# because this form of condition releases a lock as _part_ of doing a -# wait, the state of that lock can be used to guarantee it. -# -# E.g., suppose thread A spawns thread B and later wants to wait for B to -# complete: -# -# In A: In B: -# -# B_done = condition() ... do work ... -# B_done.acquire() B_done.acquire(); B_done.release() -# spawn B B_done.signal() -# ... some time later ... ... and B exits ... -# B_done.wait() -# -# Because B_done was in the acquire'd state at the time B was spawned, -# B's attempt to acquire B_done can't succeed until A has done its -# B_done.wait() (which releases B_done). So B's B_done.signal() is -# guaranteed to be seen by the .wait(). Without the lock trick, B -# may signal before A .waits, and then A would wait forever. -# -# BARRIERS -# -# A barrier object is created via -# import this_module -# your_barrier = this_module.barrier(num_threads) -# -# Methods: -# .enter() -# the thread blocks until num_threads threads in all have done -# .enter(). Then the num_threads threads that .enter'ed resume, -# and the barrier resets to capture the next num_threads threads -# that .enter it. -# -# EVENTS -# -# An event object is created via -# import this_module -# your_event = this_module.event() -# -# An event has two states, `posted' and `cleared'. An event is -# created in the cleared state. -# -# Methods: -# -# .post() -# Put the event in the posted state, and resume all threads -# .wait'ing on the event (if any). -# -# .clear() -# Put the event in the cleared state. -# -# .is_posted() -# Returns 0 if the event is in the cleared state, or 1 if the event -# is in the posted state. -# -# .wait() -# If the event is in the posted state, returns immediately. -# If the event is in the cleared state, blocks the calling thread -# until the event is .post'ed by another thread. -# -# Note that an event, once posted, remains posted until explicitly -# cleared. Relative to conditions, this is both the strength & weakness -# of events. It's a strength because the .post'ing thread doesn't have to -# worry about whether the threads it's trying to communicate with have -# already done a .wait (a condition .signal is seen only by threads that -# do a .wait _prior_ to the .signal; a .signal does not persist). But -# it's a weakness because .clear'ing an event is error-prone: it's easy -# to mistakenly .clear an event before all the threads you intended to -# see the event get around to .wait'ing on it. But so long as you don't -# need to .clear an event, events are easy to use safely. -# -# SEMAPHORES -# -# A semaphore object is created via -# import this_module -# your_semaphore = this_module.semaphore(count=1) -# -# A semaphore has an integer count associated with it. The initial value -# of the count is specified by the optional argument (which defaults to -# 1) passed to the semaphore constructor. -# -# Methods: -# -# .p() -# If the semaphore's count is greater than 0, decrements the count -# by 1 and returns. -# Else if the semaphore's count is 0, blocks the calling thread -# until a subsequent .v() increases the count. When that happens, -# the count will be decremented by 1 and the calling thread resumed. -# -# .v() -# Increments the semaphore's count by 1, and wakes up a thread (if -# any) blocked by a .p(). It's an (detected) error for a .v() to -# increase the semaphore's count to a value larger than the initial -# count. -# -# MULTIPLE-READER SINGLE-WRITER LOCKS -# -# A mrsw lock is created via -# import this_module -# your_mrsw_lock = this_module.mrsw() -# -# This kind of lock is often useful with complex shared data structures. -# The object lets any number of "readers" proceed, so long as no thread -# wishes to "write". When a (one or more) thread declares its intention -# to "write" (e.g., to update a shared structure), all current readers -# are allowed to finish, and then a writer gets exclusive access; all -# other readers & writers are blocked until the current writer completes. -# Finally, if some thread is waiting to write and another is waiting to -# read, the writer takes precedence. -# -# Methods: -# -# .read_in() -# If no thread is writing or waiting to write, returns immediately. -# Else blocks until no thread is writing or waiting to write. So -# long as some thread has completed a .read_in but not a .read_out, -# writers are blocked. -# -# .read_out() -# Use sometime after a .read_in to declare that the thread is done -# reading. When all threads complete reading, a writer can proceed. -# -# .write_in() -# If no thread is writing (has completed a .write_in, but hasn't yet -# done a .write_out) or reading (similarly), returns immediately. -# Else blocks the calling thread, and threads waiting to read, until -# the current writer completes writing or all the current readers -# complete reading; if then more than one thread is waiting to -# write, one of them is allowed to proceed, but which one is not -# specified. -# -# .write_out() -# Use sometime after a .write_in to declare that the thread is done -# writing. Then if some other thread is waiting to write, it's -# allowed to proceed. Else all threads (if any) waiting to read are -# allowed to proceed. -# -# .write_to_read() -# Use instead of a .write_in to declare that the thread is done -# writing but wants to continue reading without other writers -# intervening. If there are other threads waiting to write, they -# are allowed to proceed only if the current thread calls -# .read_out; threads waiting to read are only allowed to proceed -# if there are are no threads waiting to write. (This is a -# weakness of the interface!) - -import _thread as thread - -class condition: - def __init__(self, lock=None): - # the lock actually used by .acquire() and .release() - if lock is None: - self.mutex = thread.allocate_lock() - else: - if hasattr(lock, 'acquire') and \ - hasattr(lock, 'release'): - self.mutex = lock - else: - raise TypeError('condition constructor requires ' \ - 'a lock argument') - - # lock used to block threads until a signal - self.checkout = thread.allocate_lock() - self.checkout.acquire() - - # internal critical-section lock, & the data it protects - self.idlock = thread.allocate_lock() - self.id = 0 - self.waiting = 0 # num waiters subject to current release - self.pending = 0 # num waiters awaiting next signal - self.torelease = 0 # num waiters to release - self.releasing = 0 # 1 iff release is in progress - - def acquire(self): - self.mutex.acquire() - - def release(self): - self.mutex.release() - - def wait(self): - mutex, checkout, idlock = self.mutex, self.checkout, self.idlock - if not mutex.locked(): - raise ValueError("condition must be .acquire'd when .wait() invoked") - - idlock.acquire() - myid = self.id - self.pending = self.pending + 1 - idlock.release() - - mutex.release() - - while 1: - checkout.acquire(); idlock.acquire() - if myid < self.id: - break - checkout.release(); idlock.release() - - self.waiting = self.waiting - 1 - self.torelease = self.torelease - 1 - if self.torelease: - checkout.release() - else: - self.releasing = 0 - if self.waiting == self.pending == 0: - self.id = 0 - idlock.release() - mutex.acquire() - - def signal(self): - self.broadcast(1) - - def broadcast(self, num = -1): - if num < -1: - raise ValueError('.broadcast called with num %r' % (num,)) - if num == 0: - return - self.idlock.acquire() - if self.pending: - self.waiting = self.waiting + self.pending - self.pending = 0 - self.id = self.id + 1 - if num == -1: - self.torelease = self.waiting - else: - self.torelease = min( self.waiting, - self.torelease + num ) - if self.torelease and not self.releasing: - self.releasing = 1 - self.checkout.release() - self.idlock.release() - -class barrier: - def __init__(self, n): - self.n = n - self.togo = n - self.full = condition() - - def enter(self): - full = self.full - full.acquire() - self.togo = self.togo - 1 - if self.togo: - full.wait() - else: - self.togo = self.n - full.broadcast() - full.release() - -class event: - def __init__(self): - self.state = 0 - self.posted = condition() - - def post(self): - self.posted.acquire() - self.state = 1 - self.posted.broadcast() - self.posted.release() - - def clear(self): - self.posted.acquire() - self.state = 0 - self.posted.release() - - def is_posted(self): - self.posted.acquire() - answer = self.state - self.posted.release() - return answer - - def wait(self): - self.posted.acquire() - if not self.state: - self.posted.wait() - self.posted.release() - -class semaphore: - def __init__(self, count=1): - if count <= 0: - raise ValueError('semaphore count %d; must be >= 1' % count) - self.count = count - self.maxcount = count - self.nonzero = condition() - - def p(self): - self.nonzero.acquire() - while self.count == 0: - self.nonzero.wait() - self.count = self.count - 1 - self.nonzero.release() - - def v(self): - self.nonzero.acquire() - if self.count == self.maxcount: - raise ValueError('.v() tried to raise semaphore count above ' \ - 'initial value %r' % self.maxcount) - self.count = self.count + 1 - self.nonzero.signal() - self.nonzero.release() - -class mrsw: - def __init__(self): - # critical-section lock & the data it protects - self.rwOK = thread.allocate_lock() - self.nr = 0 # number readers actively reading (not just waiting) - self.nw = 0 # number writers either waiting to write or writing - self.writing = 0 # 1 iff some thread is writing - - # conditions - self.readOK = condition(self.rwOK) # OK to unblock readers - self.writeOK = condition(self.rwOK) # OK to unblock writers - - def read_in(self): - self.rwOK.acquire() - while self.nw: - self.readOK.wait() - self.nr = self.nr + 1 - self.rwOK.release() - - def read_out(self): - self.rwOK.acquire() - if self.nr <= 0: - raise ValueError('.read_out() invoked without an active reader') - self.nr = self.nr - 1 - if self.nr == 0: - self.writeOK.signal() - self.rwOK.release() - - def write_in(self): - self.rwOK.acquire() - self.nw = self.nw + 1 - while self.writing or self.nr: - self.writeOK.wait() - self.writing = 1 - self.rwOK.release() - - def write_out(self): - self.rwOK.acquire() - if not self.writing: - raise ValueError('.write_out() invoked without an active writer') - self.writing = 0 - self.nw = self.nw - 1 - if self.nw: - self.writeOK.signal() - else: - self.readOK.broadcast() - self.rwOK.release() - - def write_to_read(self): - self.rwOK.acquire() - if not self.writing: - raise ValueError('.write_to_read() invoked without an active writer') - self.writing = 0 - self.nw = self.nw - 1 - self.nr = self.nr + 1 - if not self.nw: - self.readOK.broadcast() - self.rwOK.release() - -# The rest of the file is a test case, that runs a number of parallelized -# quicksorts in parallel. If it works, you'll get about 600 lines of -# tracing output, with a line like -# test passed! 209 threads created in all -# as the last line. The content and order of preceding lines will -# vary across runs. - -def _new_thread(func, *args): - global TID - tid.acquire(); id = TID = TID+1; tid.release() - io.acquire(); alive.append(id); \ - print('starting thread', id, '--', len(alive), 'alive'); \ - io.release() - thread.start_new_thread( func, (id,) + args ) - -def _qsort(tid, a, l, r, finished): - # sort a[l:r]; post finished when done - io.acquire(); print('thread', tid, 'qsort', l, r); io.release() - if r-l > 1: - pivot = a[l] - j = l+1 # make a[l:j] <= pivot, and a[j:r] > pivot - for i in range(j, r): - if a[i] <= pivot: - a[j], a[i] = a[i], a[j] - j = j + 1 - a[l], a[j-1] = a[j-1], pivot - - l_subarray_sorted = event() - r_subarray_sorted = event() - _new_thread(_qsort, a, l, j-1, l_subarray_sorted) - _new_thread(_qsort, a, j, r, r_subarray_sorted) - l_subarray_sorted.wait() - r_subarray_sorted.wait() - - io.acquire(); print('thread', tid, 'qsort done'); \ - alive.remove(tid); io.release() - finished.post() - -def _randarray(tid, a, finished): - io.acquire(); print('thread', tid, 'randomizing array'); \ - io.release() - for i in range(1, len(a)): - wh.acquire(); j = randint(0,i); wh.release() - a[i], a[j] = a[j], a[i] - io.acquire(); print('thread', tid, 'randomizing done'); \ - alive.remove(tid); io.release() - finished.post() - -def _check_sort(a): - if a != range(len(a)): - raise ValueError('a not sorted', a) - -def _run_one_sort(tid, a, bar, done): - # randomize a, and quicksort it - # for variety, all the threads running this enter a barrier - # at the end, and post `done' after the barrier exits - io.acquire(); print('thread', tid, 'randomizing', a); \ - io.release() - finished = event() - _new_thread(_randarray, a, finished) - finished.wait() - - io.acquire(); print('thread', tid, 'sorting', a); io.release() - finished.clear() - _new_thread(_qsort, a, 0, len(a), finished) - finished.wait() - _check_sort(a) - - io.acquire(); print('thread', tid, 'entering barrier'); \ - io.release() - bar.enter() - io.acquire(); print('thread', tid, 'leaving barrier'); \ - io.release() - io.acquire(); alive.remove(tid); io.release() - bar.enter() # make sure they've all removed themselves from alive - ## before 'done' is posted - bar.enter() # just to be cruel - done.post() - -def test(): - global TID, tid, io, wh, randint, alive - import random - randint = random.randint - - TID = 0 # thread ID (1, 2, ...) - tid = thread.allocate_lock() # for changing TID - io = thread.allocate_lock() # for printing, and 'alive' - wh = thread.allocate_lock() # for calls to random - alive = [] # IDs of active threads - - NSORTS = 5 - arrays = [] - for i in range(NSORTS): - arrays.append( range( (i+1)*10 ) ) - - bar = barrier(NSORTS) - finished = event() - for i in range(NSORTS): - _new_thread(_run_one_sort, arrays[i], bar, finished) - finished.wait() - - print('all threads done, and checking results ...') - if alive: - raise ValueError('threads still alive at end', alive) - for i in range(NSORTS): - a = arrays[i] - if len(a) != (i+1)*10: - raise ValueError('length of array', i, 'screwed up') - _check_sort(a) - - print('test passed!', TID, 'threads created in all') - -if __name__ == '__main__': - test() - -# end of module diff --git a/Demo/threads/telnet.py b/Demo/threads/telnet.py deleted file mode 100644 index dfe4905..0000000 --- a/Demo/threads/telnet.py +++ /dev/null @@ -1,114 +0,0 @@ -# Minimal interface to the Internet telnet protocol. -# -# *** modified to use threads *** -# -# It refuses all telnet options and does not recognize any of the other -# telnet commands, but can still be used to connect in line-by-line mode. -# It's also useful to play with a number of other services, -# like time, finger, smtp and even ftp. -# -# Usage: telnet host [port] -# -# The port may be a service name or a decimal port number; -# it defaults to 'telnet'. - - -import sys, os, time -from socket import * -import _thread as thread - -BUFSIZE = 8*1024 - -# Telnet protocol characters - -IAC = chr(255) # Interpret as command -DONT = chr(254) -DO = chr(253) -WONT = chr(252) -WILL = chr(251) - -def main(): - if len(sys.argv) < 2: - sys.stderr.write('usage: telnet hostname [port]\n') - sys.exit(2) - host = sys.argv[1] - try: - hostaddr = gethostbyname(host) - except error: - sys.stderr.write(sys.argv[1] + ': bad host name\n') - sys.exit(2) - # - if len(sys.argv) > 2: - servname = sys.argv[2] - else: - servname = 'telnet' - # - if '0' <= servname[:1] <= '9': - port = eval(servname) - else: - try: - port = getservbyname(servname, 'tcp') - except error: - sys.stderr.write(servname + ': bad tcp service name\n') - sys.exit(2) - # - s = socket(AF_INET, SOCK_STREAM) - # - try: - s.connect((host, port)) - except error as msg: - sys.stderr.write('connect failed: %r\n' % (msg,)) - sys.exit(1) - # - thread.start_new(child, (s,)) - parent(s) - -def parent(s): - # read socket, write stdout - iac = 0 # Interpret next char as command - opt = '' # Interpret next char as option - while 1: - data, dummy = s.recvfrom(BUFSIZE) - if not data: - # EOF -- exit - sys.stderr.write( '(Closed by remote host)\n') - sys.exit(1) - cleandata = '' - for c in data: - if opt: - print(ord(c)) -## print '(replying: %r)' % (opt+c,) - s.send(opt + c) - opt = '' - elif iac: - iac = 0 - if c == IAC: - cleandata = cleandata + c - elif c in (DO, DONT): - if c == DO: print('(DO)', end=' ') - else: print('(DONT)', end=' ') - opt = IAC + WONT - elif c in (WILL, WONT): - if c == WILL: print('(WILL)', end=' ') - else: print('(WONT)', end=' ') - opt = IAC + DONT - else: - print('(command)', ord(c)) - elif c == IAC: - iac = 1 - print('(IAC)', end=' ') - else: - cleandata = cleandata + c - sys.stdout.write(cleandata) - sys.stdout.flush() -## print 'Out:', repr(cleandata) - -def child(s): - # read stdin, write socket - while 1: - line = sys.stdin.readline() -## print 'Got:', repr(line) - if not line: break - s.send(line) - -main() diff --git a/Demo/xml/elem_count.py b/Demo/xml/elem_count.py deleted file mode 100644 index 99d6ca9..0000000 --- a/Demo/xml/elem_count.py +++ /dev/null @@ -1,42 +0,0 @@ -""" -A simple demo that reads in an XML document and displays the number of -elements and attributes as well as a tally of elements and attributes by name. -""" - -import sys -from collections import defaultdict - -from xml.sax import make_parser, handler - -class FancyCounter(handler.ContentHandler): - - def __init__(self): - self._elems = 0 - self._attrs = 0 - self._elem_types = defaultdict(int) - self._attr_types = defaultdict(int) - - def startElement(self, name, attrs): - self._elems += 1 - self._attrs += len(attrs) - self._elem_types[name] += 1 - - for name in attrs.keys(): - self._attr_types[name] += 1 - - def endDocument(self): - print("There were", self._elems, "elements.") - print("There were", self._attrs, "attributes.") - - print("---ELEMENT TYPES") - for pair in self._elem_types.items(): - print("%20s %d" % pair) - - print("---ATTRIBUTE TYPES") - for pair in self._attr_types.items(): - print("%20s %d" % pair) - -if __name__ == '__main__': - parser = make_parser() - parser.setContentHandler(FancyCounter()) - parser.parse(sys.argv[1]) diff --git a/Demo/xml/roundtrip.py b/Demo/xml/roundtrip.py deleted file mode 100644 index 801c009..0000000 --- a/Demo/xml/roundtrip.py +++ /dev/null @@ -1,46 +0,0 @@ -""" -A simple demo that reads in an XML document and spits out an equivalent, -but not necessarily identical, document. -""" - -import sys - -from xml.sax import saxutils, handler, make_parser - -# --- The ContentHandler - -class ContentGenerator(handler.ContentHandler): - - def __init__(self, out=sys.stdout): - handler.ContentHandler.__init__(self) - self._out = out - - # ContentHandler methods - - def startDocument(self): - self._out.write('<?xml version="1.0" encoding="iso-8859-1"?>\n') - - def startElement(self, name, attrs): - self._out.write('<' + name) - for (name, value) in attrs.items(): - self._out.write(' %s="%s"' % (name, saxutils.escape(value))) - self._out.write('>') - - def endElement(self, name): - self._out.write('</%s>' % name) - - def characters(self, content): - self._out.write(saxutils.escape(content)) - - def ignorableWhitespace(self, content): - self._out.write(content) - - def processingInstruction(self, target, data): - self._out.write('<?%s %s?>' % (target, data)) - -# --- The main program - -if __name__ == '__main__': - parser = make_parser() - parser.setContentHandler(ContentGenerator()) - parser.parse(sys.argv[1]) diff --git a/Demo/xml/rss2html.py b/Demo/xml/rss2html.py deleted file mode 100644 index 49cd154..0000000 --- a/Demo/xml/rss2html.py +++ /dev/null @@ -1,97 +0,0 @@ -""" -A demo that reads in an RSS XML document and emits an HTML file containing -a list of the individual items in the feed. -""" - -import sys -import codecs - -from xml.sax import make_parser, handler - -# --- Templates - -top = """\ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> -<html> -<head> - <title>%s</title> - <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> -</head> - -<body> -<h1>%s</h1> -""" - -bottom = """ -</ul> - -<hr> -<address> -Converted to HTML by rss2html.py. -</address> - -</body> -</html> -""" - -# --- The ContentHandler - -class RSSHandler(handler.ContentHandler): - - def __init__(self, out=sys.stdout): - handler.ContentHandler.__init__(self) - self._out = out - - self._text = "" - self._parent = None - self._list_started = False - self._title = None - self._link = None - self._descr = "" - - # ContentHandler methods - - def startElement(self, name, attrs): - if name == "channel" or name == "image" or name == "item": - self._parent = name - - self._text = "" - - def endElement(self, name): - if self._parent == "channel": - if name == "title": - self._out.write(top % (self._text, self._text)) - elif name == "description": - self._out.write("<p>%s</p>\n" % self._text) - - elif self._parent == "item": - if name == "title": - self._title = self._text - elif name == "link": - self._link = self._text - elif name == "description": - self._descr = self._text - elif name == "item": - if not self._list_started: - self._out.write("<ul>\n") - self._list_started = True - - self._out.write(' <li><a href="%s">%s</a> %s\n' % - (self._link, self._title, self._descr)) - - self._title = None - self._link = None - self._descr = "" - - if name == "rss": - self._out.write(bottom) - - def characters(self, content): - self._text = self._text + content - -# --- Main program - -if __name__ == '__main__': - parser = make_parser() - parser.setContentHandler(RSSHandler()) - parser.parse(sys.argv[1]) diff --git a/Demo/zlib/minigzip.py b/Demo/zlib/minigzip.py deleted file mode 100755 index b57de73..0000000 --- a/Demo/zlib/minigzip.py +++ /dev/null @@ -1,134 +0,0 @@ -#!/usr/bin/env python3 -# Demo program for zlib; it compresses or decompresses files, but *doesn't* -# delete the original. This doesn't support all of gzip's options. -# -# The 'gzip' module in the standard library provides a more complete -# implementation of gzip-format files. - -import zlib, sys, os - -FTEXT, FHCRC, FEXTRA, FNAME, FCOMMENT = 1, 2, 4, 8, 16 - -def write32(output, value): - output.write(bytes([value & 255])) ; value=value // 256 - output.write(bytes([value & 255])) ; value=value // 256 - output.write(bytes([value & 255])) ; value=value // 256 - output.write(bytes([value & 255])) - -def read32(input): - v = ord(input.read(1)) - v += (ord(input.read(1)) << 8 ) - v += (ord(input.read(1)) << 16) - v += (ord(input.read(1)) << 24) - return v - -def compress(filename, input, output): - output.write(b'\037\213\010') # Write the header, ... - output.write(bytes([FNAME])) # ... flag byte ... - - statval = os.stat(filename) # ... modification time ... - mtime = statval[8] - write32(output, mtime) - output.write(b'\002') # ... slowest compression alg. ... - output.write(b'\377') # ... OS (=unknown) ... - bfilename = os.fsencode(filename) - output.write(bfilename + b'\000') # ... original filename ... - - crcval = zlib.crc32(b'') - compobj = zlib.compressobj(9, zlib.DEFLATED, -zlib.MAX_WBITS, - zlib.DEF_MEM_LEVEL, 0) - while True: - data = input.read(1024) - if data == b'': - break - crcval = zlib.crc32(data, crcval) - output.write(compobj.compress(data)) - output.write(compobj.flush()) - write32(output, crcval) # ... the CRC ... - write32(output, statval[6]) # and the file size. - -def decompress(input, output): - magic = input.read(2) - if magic != b'\037\213': - print('Not a gzipped file') - sys.exit(0) - if ord(input.read(1)) != 8: - print('Unknown compression method') - sys.exit(0) - flag = ord(input.read(1)) - input.read(4+1+1) # Discard modification time, - # extra flags, and OS byte. - if flag & FEXTRA: - # Read & discard the extra field, if present - xlen = ord(input.read(1)) - xlen += 256*ord(input.read(1)) - input.read(xlen) - if flag & FNAME: - # Read and discard a null-terminated string containing the filename - while True: - s = input.read(1) - if s == b'\0': break - if flag & FCOMMENT: - # Read and discard a null-terminated string containing a comment - while True: - s = input.read(1) - if s == b'\0': break - if flag & FHCRC: - input.read(2) # Read & discard the 16-bit header CRC - - decompobj = zlib.decompressobj(-zlib.MAX_WBITS) - crcval = zlib.crc32(b'') - length = 0 - while True: - data = input.read(1024) - if data == b"": - break - decompdata = decompobj.decompress(data) - output.write(decompdata) - length += len(decompdata) - crcval = zlib.crc32(decompdata, crcval) - - decompdata = decompobj.flush() - output.write(decompdata) - length += len(decompdata) - crcval = zlib.crc32(decompdata, crcval) - - # We've read to the end of the file, so we have to rewind in order - # to reread the 8 bytes containing the CRC and the file size. The - # decompressor is smart and knows when to stop, so feeding it - # extra data is harmless. - input.seek(-8, 2) - crc32 = read32(input) - isize = read32(input) - if crc32 != crcval: - print('CRC check failed.') - if isize != length: - print('Incorrect length of data produced') - -def main(): - if len(sys.argv)!=2: - print('Usage: minigzip.py <filename>') - print(' The file will be compressed or decompressed.') - sys.exit(0) - - filename = sys.argv[1] - if filename.endswith('.gz'): - compressing = False - outputname = filename[:-3] - else: - compressing = True - outputname = filename + '.gz' - - input = open(filename, 'rb') - output = open(outputname, 'wb') - - if compressing: - compress(filename, input, output) - else: - decompress(input, output) - - input.close() - output.close() - -if __name__ == '__main__': - main() diff --git a/Demo/zlib/zlibdemo.py b/Demo/zlib/zlibdemo.py deleted file mode 100755 index 40a36d4..0000000 --- a/Demo/zlib/zlibdemo.py +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env python3 - -# Takes an optional filename, defaulting to this file itself. -# Reads the file and compresses the content using level 1 and level 9 -# compression, printing a summary of the results. - -import zlib, sys - -def main(): - if len(sys.argv) > 1: - filename = sys.argv[1] - else: - filename = sys.argv[0] - print('Reading', filename) - - with open(filename, 'rb') as f: # Get the data to compress - s = f.read() - - # First, we'll compress the string in one step - comptext = zlib.compress(s, 1) - decomp = zlib.decompress(comptext) - - print('1-step compression: (level 1)') - print(' Original:', len(s), 'Compressed:', len(comptext), end=' ') - print('Uncompressed:', len(decomp)) - - # Now, let's compress the string in stages; set chunk to work in smaller steps - - chunk = 256 - compressor = zlib.compressobj(9) - decompressor = zlib.decompressobj() - comptext = decomp = b'' - for i in range(0, len(s), chunk): - comptext += compressor.compress(s[i:i+chunk]) - # Don't forget to call flush()!! - comptext += compressor.flush() - - for i in range(0, len(comptext), chunk): - decomp += decompressor.decompress(comptext[i:i+chunk]) - decomp += decompressor.flush() - - print('Progressive compression (level 9):') - print(' Original:', len(s), 'Compressed:', len(comptext), end=' ') - print('Uncompressed:', len(decomp)) - -if __name__ == '__main__': - main() diff --git a/Doc/library/pty.rst b/Doc/library/pty.rst index d039fdf..2b9385b 100644 --- a/Doc/library/pty.rst +++ b/Doc/library/pty.rst @@ -45,3 +45,50 @@ The :mod:`pty` module defines the following functions: a file descriptor. The defaults try to read 1024 bytes each time they are called. + +Example +------- + +.. sectionauthor:: Steen Lumholt + +The following program acts like the Unix command :manpage:`script(1)`, using a +pseudo-terminal to record all input and output of a terminal session in a +"typescript". :: + + import sys, os, time, getopt + import pty + + mode = 'wb' + shell = 'sh' + filename = 'typescript' + if 'SHELL' in os.environ: + shell = os.environ['SHELL'] + + try: + opts, args = getopt.getopt(sys.argv[1:], 'ap') + except getopt.error as msg: + print('%s: %s' % (sys.argv[0], msg)) + sys.exit(2) + + for opt, arg in opts: + # option -a: append to typescript file + if opt == '-a': + mode = 'ab' + # option -p: use a Python shell as the terminal command + elif opt == '-p': + shell = sys.executable + if args: + filename = args[0] + + script = open(filename, mode) + + def read(fd): + data = os.read(fd, 1024) + script.write(data) + return data + + sys.stdout.write('Script started, file is %s\n' % filename) + script.write(('Script started on %s\n' % time.asctime()).encode()) + pty.spawn(shell, read) + script.write(('Script done on %s\n' % time.asctime()).encode()) + sys.stdout.write('Script done, file is %s\n' % filename) diff --git a/Demo/parser/test_unparse.py b/Tools/parser/test_unparse.py index d457523..d457523 100644 --- a/Demo/parser/test_unparse.py +++ b/Tools/parser/test_unparse.py diff --git a/Demo/parser/unparse.py b/Tools/parser/unparse.py index e96ef54..e96ef54 100644 --- a/Demo/parser/unparse.py +++ b/Tools/parser/unparse.py diff --git a/Demo/scripts/find-uname.py b/Tools/scripts/find-uname.py index b6ec1b6..b6ec1b6 100755 --- a/Demo/scripts/find-uname.py +++ b/Tools/scripts/find-uname.py |