[Python-checkins] r75857 - in python/branches/release31-maint: Demo/scripts/README Demo/scripts/beer.py Demo/scripts/fact.py Demo/scripts/find-uname.py Demo/scripts/ftpstats.py Demo/scripts/lpwatch.py Demo/scripts/markov.py Demo/scripts/mkrcs.py Demo/scripts/morse.py Demo/scripts/newslist.py Demo/scripts/pi.py Demo/scripts/pp.py Demo/scripts/queens.py Demo/scripts/script.py Demo/scripts/unbirthday.py Demo/xml/elem_count.py Demo/xml/roundtrip.py Demo/xml/rss2html.py Doc/library/configparser.rst Doc/library/copy.rst Doc/library/marshal.rst Doc/library/urllib.parse.rst Doc/reference/datamodel.rst Lib/pdb.py Lib/pydoc.py Lib/test/test_funcattrs.py Lib/test/test_pdb.py

georg.brandl python-checkins at python.org
Tue Oct 27 21:19:04 CET 2009


Author: georg.brandl
Date: Tue Oct 27 21:19:02 2009
New Revision: 75857

Log:
Merged revisions 74609,74627,74634,74645,74651,74738,74840,75016,75316-75317,75323-75324,75326,75328,75330,75338,75340-75341,75343,75352-75353,75355,75357,75359 via svnmerge from 
svn+ssh://svn.python.org/python/branches/py3k

................
  r74609 | senthil.kumaran | 2009-08-31 18:43:45 +0200 (Mo, 31 Aug 2009) | 3 lines
  
  Doc fix for issue2637.
................
  r74627 | georg.brandl | 2009-09-02 22:31:26 +0200 (Mi, 02 Sep 2009) | 1 line
  
  #6819: fix typo.
................
  r74634 | georg.brandl | 2009-09-03 14:34:10 +0200 (Do, 03 Sep 2009) | 9 lines
  
  Merged revisions 74633 via svnmerge from 
  svn+ssh://pythondev@svn.python.org/python/trunk
  
  ........
    r74633 | georg.brandl | 2009-09-03 14:31:39 +0200 (Do, 03 Sep 2009) | 1 line
    
    #6757: complete the list of types that marshal can serialize.
  ........
................
  r74645 | georg.brandl | 2009-09-04 10:07:32 +0200 (Fr, 04 Sep 2009) | 1 line
  
  #5221: fix related topics: SEQUENCEMETHODS[12] doesnt exist any more.
................
  r74651 | georg.brandl | 2009-09-04 13:20:54 +0200 (Fr, 04 Sep 2009) | 9 lines
  
  Recorded merge of revisions 74650 via svnmerge from 
  svn+ssh://pythondev@svn.python.org/python/trunk
  
  ........
    r74650 | georg.brandl | 2009-09-04 13:19:34 +0200 (Fr, 04 Sep 2009) | 1 line
    
    #5101: add back tests to test_funcattrs that were lost during unittest conversion, and make some PEP8 cleanups.
  ........
................
  r74738 | georg.brandl | 2009-09-09 18:51:05 +0200 (Mi, 09 Sep 2009) | 9 lines
  
  Merged revisions 74737 via svnmerge from 
  svn+ssh://pythondev@svn.python.org/python/trunk
  
  ........
    r74737 | georg.brandl | 2009-09-09 18:49:13 +0200 (Mi, 09 Sep 2009) | 1 line
    
    Properly document copy and deepcopy as functions.
  ........
................
  r74840 | georg.brandl | 2009-09-16 18:40:45 +0200 (Mi, 16 Sep 2009) | 13 lines
  
  Merged revisions 74838-74839 via svnmerge from 
  svn+ssh://pythondev@svn.python.org/python/trunk
  
  ........
    r74838 | georg.brandl | 2009-09-16 18:22:12 +0200 (Mi, 16 Sep 2009) | 1 line
    
    Remove some more boilerplate from the actual tests in test_pdb.
  ........
    r74839 | georg.brandl | 2009-09-16 18:36:39 +0200 (Mi, 16 Sep 2009) | 1 line
    
    Make the pdb displayhook compatible with the standard displayhook: do not print Nones. Add a test for that.
  ........
................
  r75016 | georg.brandl | 2009-09-22 15:53:14 +0200 (Di, 22 Sep 2009) | 1 line
  
  #6969: make it explicit that configparser writes/reads text files, and fix the example.
................
  r75316 | georg.brandl | 2009-10-10 23:12:35 +0200 (Sa, 10 Okt 2009) | 9 lines
  
  Merged revisions 75313 via svnmerge from 
  svn+ssh://pythondev@svn.python.org/python/trunk
  
  ........
    r75313 | georg.brandl | 2009-10-10 23:07:35 +0200 (Sa, 10 Okt 2009) | 1 line
    
    Bring old demo up-to-date.
  ........
................
  r75317 | georg.brandl | 2009-10-10 23:13:21 +0200 (Sa, 10 Okt 2009) | 9 lines
  
  Merged revisions 75315 via svnmerge from 
  svn+ssh://pythondev@svn.python.org/python/trunk
  
  ........
    r75315 | georg.brandl | 2009-10-10 23:10:05 +0200 (Sa, 10 Okt 2009) | 1 line
    
    Remove unneeded "L" suffixes.
  ........
................
  r75323 | georg.brandl | 2009-10-10 23:48:05 +0200 (Sa, 10 Okt 2009) | 9 lines
  
  Recorded merge of revisions 75321 via svnmerge from 
  svn+ssh://pythondev@svn.python.org/python/trunk
  
  ........
    r75321 | georg.brandl | 2009-10-10 23:43:21 +0200 (Sa, 10 Okt 2009) | 1 line
    
    Remove outdated comment and fix a few style issues.
  ........
................
  r75324 | georg.brandl | 2009-10-10 23:49:24 +0200 (Sa, 10 Okt 2009) | 9 lines
  
  Merged revisions 75322 via svnmerge from 
  svn+ssh://pythondev@svn.python.org/python/trunk
  
  ........
    r75322 | georg.brandl | 2009-10-10 23:47:31 +0200 (Sa, 10 Okt 2009) | 1 line
    
    Show use of range() step argument nicely.
  ........
................
  r75326 | georg.brandl | 2009-10-10 23:57:03 +0200 (Sa, 10 Okt 2009) | 9 lines
  
  Merged revisions 75325 via svnmerge from 
  svn+ssh://pythondev@svn.python.org/python/trunk
  
  ........
    r75325 | georg.brandl | 2009-10-10 23:55:11 +0200 (Sa, 10 Okt 2009) | 1 line
    
    Modernize factorisation demo (mostly augassign.)
  ........
................
  r75328 | georg.brandl | 2009-10-11 00:05:26 +0200 (So, 11 Okt 2009) | 9 lines
  
  Merged revisions 75327 via svnmerge from 
  svn+ssh://pythondev@svn.python.org/python/trunk
  
  ........
    r75327 | georg.brandl | 2009-10-11 00:03:43 +0200 (So, 11 Okt 2009) | 1 line
    
    Style fixes.
  ........
................
  r75330 | georg.brandl | 2009-10-11 00:32:28 +0200 (So, 11 Okt 2009) | 9 lines
  
  Merged revisions 75329 via svnmerge from 
  svn+ssh://pythondev@svn.python.org/python/trunk
  
  ........
    r75329 | georg.brandl | 2009-10-11 00:26:45 +0200 (So, 11 Okt 2009) | 1 line
    
    Modernize all around (dont ask me how useful that script is nowadays...)
  ........
................
  r75338 | georg.brandl | 2009-10-11 10:31:41 +0200 (So, 11 Okt 2009) | 9 lines
  
  Merged revisions 75337 via svnmerge from 
  svn+ssh://pythondev@svn.python.org/python/trunk
  
  ........
    r75337 | georg.brandl | 2009-10-11 10:18:44 +0200 (So, 11 Okt 2009) | 1 line
    
    Update morse script, avoid globals, use iterators.
  ........
................
  r75340 | georg.brandl | 2009-10-11 10:42:09 +0200 (So, 11 Okt 2009) | 9 lines
  
  Merged revisions 75339 via svnmerge from 
  svn+ssh://pythondev@svn.python.org/python/trunk
  
  ........
    r75339 | georg.brandl | 2009-10-11 10:39:16 +0200 (So, 11 Okt 2009) | 1 line
    
    Update markov demo.
  ........
................
  r75341 | georg.brandl | 2009-10-11 10:43:08 +0200 (So, 11 Okt 2009) | 1 line
  
  Fix README description.
................
  r75343 | georg.brandl | 2009-10-11 10:46:56 +0200 (So, 11 Okt 2009) | 9 lines
  
  Merged revisions 75342 via svnmerge from 
  svn+ssh://pythondev@svn.python.org/python/trunk
  
  ........
    r75342 | georg.brandl | 2009-10-11 10:45:03 +0200 (So, 11 Okt 2009) | 1 line
    
    Remove useless script "mkrcs" and update README.
  ........
................
  r75352 | georg.brandl | 2009-10-11 14:04:10 +0200 (So, 11 Okt 2009) | 9 lines
  
  Merged revisions 75350 via svnmerge from 
  svn+ssh://pythondev@svn.python.org/python/trunk
  
  ........
    r75350 | georg.brandl | 2009-10-11 14:00:18 +0200 (So, 11 Okt 2009) | 1 line
    
    Use getopt in script.py demo.
  ........
................
  r75353 | georg.brandl | 2009-10-11 14:04:40 +0200 (So, 11 Okt 2009) | 9 lines
  
  Merged revisions 75351 via svnmerge from 
  svn+ssh://pythondev@svn.python.org/python/trunk
  
  ........
    r75351 | georg.brandl | 2009-10-11 14:03:01 +0200 (So, 11 Okt 2009) | 1 line
    
    Fix variable.
  ........
................
  r75355 | georg.brandl | 2009-10-11 16:27:51 +0200 (So, 11 Okt 2009) | 9 lines
  
  Merged revisions 75354 via svnmerge from 
  svn+ssh://pythondev@svn.python.org/python/trunk
  
  ........
    r75354 | georg.brandl | 2009-10-11 16:23:49 +0200 (So, 11 Okt 2009) | 1 line
    
    Update lpwatch script.
  ........
................
  r75357 | georg.brandl | 2009-10-11 16:50:57 +0200 (So, 11 Okt 2009) | 9 lines
  
  Merged revisions 75356 via svnmerge from 
  svn+ssh://pythondev@svn.python.org/python/trunk
  
  ........
    r75356 | georg.brandl | 2009-10-11 16:49:37 +0200 (So, 11 Okt 2009) | 1 line
    
    Remove ftpstats script, the daemon whose log files it reads is long gone.
  ........
................
  r75359 | georg.brandl | 2009-10-11 17:56:06 +0200 (So, 11 Okt 2009) | 9 lines
  
  Merged revisions 75358 via svnmerge from 
  svn+ssh://pythondev@svn.python.org/python/trunk
  
  ........
    r75358 | georg.brandl | 2009-10-11 17:06:44 +0200 (So, 11 Okt 2009) | 1 line
    
    Overhaul of Demo/xml.
  ........
................


Added:
   python/branches/release31-maint/Demo/scripts/morse.py
      - copied unchanged from r75343, /python/branches/py3k/Demo/scripts/morse.py
Removed:
   python/branches/release31-maint/Demo/scripts/ftpstats.py
   python/branches/release31-maint/Demo/scripts/mkrcs.py
Modified:
   python/branches/release31-maint/   (props changed)
   python/branches/release31-maint/Demo/scripts/README
   python/branches/release31-maint/Demo/scripts/beer.py
   python/branches/release31-maint/Demo/scripts/fact.py
   python/branches/release31-maint/Demo/scripts/find-uname.py
   python/branches/release31-maint/Demo/scripts/lpwatch.py
   python/branches/release31-maint/Demo/scripts/markov.py
   python/branches/release31-maint/Demo/scripts/newslist.py
   python/branches/release31-maint/Demo/scripts/pi.py
   python/branches/release31-maint/Demo/scripts/pp.py
   python/branches/release31-maint/Demo/scripts/queens.py
   python/branches/release31-maint/Demo/scripts/script.py
   python/branches/release31-maint/Demo/scripts/unbirthday.py
   python/branches/release31-maint/Demo/xml/elem_count.py
   python/branches/release31-maint/Demo/xml/roundtrip.py
   python/branches/release31-maint/Demo/xml/rss2html.py
   python/branches/release31-maint/Doc/library/configparser.rst
   python/branches/release31-maint/Doc/library/copy.rst
   python/branches/release31-maint/Doc/library/marshal.rst
   python/branches/release31-maint/Doc/library/urllib.parse.rst
   python/branches/release31-maint/Doc/reference/datamodel.rst
   python/branches/release31-maint/Lib/pdb.py
   python/branches/release31-maint/Lib/pydoc.py
   python/branches/release31-maint/Lib/test/test_funcattrs.py
   python/branches/release31-maint/Lib/test/test_pdb.py

Modified: python/branches/release31-maint/Demo/scripts/README
==============================================================================
--- python/branches/release31-maint/Demo/scripts/README	(original)
+++ python/branches/release31-maint/Demo/scripts/README	Tue Oct 27 21:19:02 2009
@@ -5,15 +5,14 @@
 beer.py			Print the classic 'bottles of beer' list.
 eqfix.py		Fix .py files to use the correct equality test operator
 fact.py			Factorize numbers
-find-uname.py		Search for Unicode characters using regexps.
+find-uname.py		Search for Unicode characters using regexps
 from.py			Summarize mailbox
-ftpstats.py		Summarize ftp daemon log file
 lpwatch.py		Watch BSD line printer queues
 makedir.py		Like mkdir -p
 markov.py		Markov chain simulation of words or characters
-mboxconvvert.py		Convert MH or MMDF mailboxes to unix mailbox format
-mkrcs.py		Fix symlinks named RCS into parallel tree
-morse.py		Produce morse code (audible or on AIFF file)
+mboxconvert.py		Convert MH or MMDF mailboxes to unix mailbox format
+morse.py		Produce morse code (as an AIFF file)
+newslist.py		List all newsgroups on a NNTP server as HTML pages
 pi.py			Print all digits of pi -- given enough time and memory
 pp.py			Emulate some Perl command line options
 primes.py		Print prime numbers

Modified: python/branches/release31-maint/Demo/scripts/beer.py
==============================================================================
--- python/branches/release31-maint/Demo/scripts/beer.py	(original)
+++ python/branches/release31-maint/Demo/scripts/beer.py	Tue Oct 27 21:19:02 2009
@@ -1,14 +1,20 @@
 #! /usr/bin/env python
+
 # By GvR, demystified after a version by Fredrik Lundh.
+
 import sys
+
 n = 100
-if sys.argv[1:]: n = int(sys.argv[1])
+if sys.argv[1:]:
+    n = int(sys.argv[1])
+
 def bottle(n):
     if n == 0: return "no more bottles of beer"
     if n == 1: return "one bottle of beer"
     return str(n) + " bottles of beer"
-for i in range(n):
-    print(bottle(n-i), "on the wall,")
-    print(bottle(n-i) + ".")
+
+for i in range(n, 0, -1):
+    print(bottle(i), "on the wall,")
+    print(bottle(i) + ".")
     print("Take one down, pass it around,")
-    print(bottle(n-i-1), "on the wall.")
+    print(bottle(i-1), "on the wall.")

Modified: python/branches/release31-maint/Demo/scripts/fact.py
==============================================================================
--- python/branches/release31-maint/Demo/scripts/fact.py	(original)
+++ python/branches/release31-maint/Demo/scripts/fact.py	Tue Oct 27 21:19:02 2009
@@ -9,39 +9,41 @@
 from math import sqrt
 
 def fact(n):
-    if n < 1: raise ValueError # fact() argument should be >= 1
-    if n == 1: return []    # special case
+    if n < 1:
+        raise ValueError('fact() argument should be >= 1')
+    if n == 1:
+        return []  # special case
     res = []
-    # Treat even factors special, so we can use i = i+2 later
-    while n%2 == 0:
+    # Treat even factors special, so we can use i += 2 later
+    while n % 2 == 0:
         res.append(2)
-        n = n//2
+        n //= 2
     # Try odd numbers up to sqrt(n)
-    limit = sqrt(float(n+1))
+    limit = sqrt(n+1)
     i = 3
     while i <= limit:
-        if n%i == 0:
+        if n % i == 0:
             res.append(i)
-            n = n//i
+            n //= i
             limit = sqrt(n+1)
         else:
-            i = i+2
+            i += 2
     if n != 1:
         res.append(n)
     return res
 
 def main():
     if len(sys.argv) > 1:
-        for arg in sys.argv[1:]:
-            n = eval(arg)
-            print(n, fact(n))
+        source = sys.argv[1:]
     else:
+        source = iter(input, '')
+    for arg in source:
         try:
-            while 1:
-                n = eval(input())
-                print(n, fact(n))
-        except EOFError:
-            pass
+            n = int(arg)
+        except ValueError:
+            print(arg, 'is not an integer')
+        else:
+            print(n, fact(n))
 
 if __name__ == "__main__":
     main()

Modified: python/branches/release31-maint/Demo/scripts/find-uname.py
==============================================================================
--- python/branches/release31-maint/Demo/scripts/find-uname.py	(original)
+++ python/branches/release31-maint/Demo/scripts/find-uname.py	Tue Oct 27 21:19:02 2009
@@ -21,20 +21,20 @@
 import re
 
 def main(args):
-    unicode_names= []
+    unicode_names = []
     for ix in range(sys.maxunicode+1):
         try:
-            unicode_names.append( (ix, unicodedata.name(chr(ix))) )
+            unicode_names.append((ix, unicodedata.name(chr(ix))))
         except ValueError: # no name for the character
             pass
     for arg in args:
         pat = re.compile(arg, re.I)
-        matches = [(x,y) for (x,y) in unicode_names
-                       if pat.search(y) is not None]
+        matches = [(y,x) for (x,y) in unicode_names
+                   if pat.search(y) is not None]
         if matches:
             print("***", arg, "matches", "***")
-            for (x,y) in matches:
-                print("%s (%d)" % (y,x))
+            for match in matches:
+                print("%s (%d)" % match)
 
 if __name__ == "__main__":
     main(sys.argv[1:])

Deleted: python/branches/release31-maint/Demo/scripts/ftpstats.py
==============================================================================
--- python/branches/release31-maint/Demo/scripts/ftpstats.py	Tue Oct 27 21:19:02 2009
+++ (empty file)
@@ -1,142 +0,0 @@
-#! /usr/bin/env python
-
-# Extract statistics from ftp daemon log.
-
-# Usage:
-# ftpstats [-m maxitems] [-s search] [file]
-# -m maxitems: restrict number of items in "top-N" lists, default 25.
-# -s string:   restrict statistics to lines containing this string.
-# Default file is /usr/adm/ftpd;  a "-" means read standard input.
-
-# The script must be run on the host where the ftp daemon runs.
-# (At CWI this is currently buizerd.)
-
-import os
-import sys
-import re
-import string
-import getopt
-
-pat = '^([a-zA-Z0-9 :]*)!(.*)!(.*)!([<>].*)!([0-9]+)!([0-9]+)$'
-prog = re.compile(pat)
-
-def main():
-    maxitems = 25
-    search = None
-    try:
-        opts, args = getopt.getopt(sys.argv[1:], 'm:s:')
-    except getopt.error as msg:
-        print(msg)
-        print('usage: ftpstats [-m maxitems] [file]')
-        sys.exit(2)
-    for o, a in opts:
-        if o == '-m':
-            maxitems = string.atoi(a)
-        if o == '-s':
-            search = a
-    file = '/usr/adm/ftpd'
-    if args: file = args[0]
-    if file == '-':
-        f = sys.stdin
-    else:
-        try:
-            f = open(file, 'r')
-        except IOError as msg:
-            print(file, ':', msg)
-            sys.exit(1)
-    bydate = {}
-    bytime = {}
-    byfile = {}
-    bydir = {}
-    byhost = {}
-    byuser = {}
-    bytype = {}
-    lineno = 0
-    try:
-        while 1:
-            line = f.readline()
-            if not line: break
-            lineno = lineno + 1
-            if search and string.find(line, search) < 0:
-                continue
-            if prog.match(line) < 0:
-                print('Bad line', lineno, ':', repr(line))
-                continue
-            items = prog.group(1, 2, 3, 4, 5, 6)
-            (logtime, loguser, loghost, logfile, logbytes,
-             logxxx2) = items
-##                      print logtime
-##                      print '-->', loguser
-##                      print '--> -->', loghost
-##                      print '--> --> -->', logfile
-##                      print '--> --> --> -->', logbytes
-##                      print '--> --> --> --> -->', logxxx2
-##                      for i in logtime, loghost, logbytes, logxxx2:
-##                              if '!' in i: print '???', i
-            add(bydate, logtime[-4:] + ' ' + logtime[:6], items)
-            add(bytime, logtime[7:9] + ':00-59', items)
-            direction, logfile = logfile[0], logfile[1:]
-            # The real path probably starts at the last //...
-            while 1:
-                i = string.find(logfile, '//')
-                if i < 0: break
-                logfile = logfile[i+1:]
-            add(byfile, logfile + ' ' + direction, items)
-            logdir = os.path.dirname(logfile)
-##              logdir = os.path.normpath(logdir) + '/.'
-            while 1:
-                add(bydir, logdir + ' ' + direction, items)
-                dirhead = os.path.dirname(logdir)
-                if dirhead == logdir: break
-                logdir = dirhead
-            add(byhost, loghost, items)
-            add(byuser, loguser, items)
-            add(bytype, direction, items)
-    except KeyboardInterrupt:
-        print('Interrupted at line', lineno)
-    show(bytype, 'by transfer direction', maxitems)
-    show(bydir, 'by directory', maxitems)
-    show(byfile, 'by file', maxitems)
-    show(byhost, 'by host', maxitems)
-    show(byuser, 'by user', maxitems)
-    showbar(bydate, 'by date')
-    showbar(bytime, 'by time of day')
-
-def showbar(dict, title):
-    n = len(title)
-    print('='*((70-n)//2), title, '='*((71-n)//2))
-    list = []
-    for key in sorted(dict.keys()):
-        n = len(str(key))
-        list.append((len(dict[key]), key))
-    maxkeylength = 0
-    maxcount = 0
-    for count, key in list:
-        maxkeylength = max(maxkeylength, len(key))
-        maxcount = max(maxcount, count)
-    maxbarlength = 72 - maxkeylength - 7
-    for count, key in list:
-        barlength = int(round(maxbarlength*float(count)/maxcount))
-        bar = '*'*barlength
-        print('%5d %-*s %s' % (count, maxkeylength, key, bar))
-
-def show(dict, title, maxitems):
-    if len(dict) > maxitems:
-        title = title + ' (first %d)'%maxitems
-    n = len(title)
-    print('='*((70-n)//2), title, '='*((71-n)//2))
-    list = []
-    for key in dict.keys():
-        list.append((-len(dict[key]), key))
-    list.sort()
-    for count, key in list[:maxitems]:
-        print('%5d %s' % (-count, key))
-
-def add(dict, key, item):
-    if key in dict:
-        dict[key].append(item)
-    else:
-        dict[key] = [item]
-
-if __name__ == "__main__":
-    main()

Modified: python/branches/release31-maint/Demo/scripts/lpwatch.py
==============================================================================
--- python/branches/release31-maint/Demo/scripts/lpwatch.py	(original)
+++ python/branches/release31-maint/Demo/scripts/lpwatch.py	Tue Oct 27 21:19:02 2009
@@ -3,10 +3,9 @@
 # Watch line printer queue(s).
 # Intended for BSD 4.3 lpq.
 
-import posix
+import os
 import sys
 import time
-import string
 
 DEF_PRINTER = 'psc'
 DEF_DELAY = 10
@@ -14,94 +13,87 @@
 def main():
     delay = DEF_DELAY # XXX Use getopt() later
     try:
-        thisuser = posix.environ['LOGNAME']
+        thisuser = os.environ['LOGNAME']
     except:
-        thisuser = posix.environ['USER']
+        thisuser = os.environ['USER']
     printers = sys.argv[1:]
     if printers:
         # Strip '-P' from printer names just in case
         # the user specified it...
-        for i in range(len(printers)):
-            if printers[i][:2] == '-P':
-                printers[i] = printers[i][2:]
+        for i, name in enumerate(printers):
+            if name[:2] == '-P':
+                printers[i] = name[2:]
     else:
-        if 'PRINTER' in posix.environ:
-            printers = [posix.environ['PRINTER']]
+        if 'PRINTER' in os.environ:
+            printers = [os.environ['PRINTER']]
         else:
             printers = [DEF_PRINTER]
-    #
-    clearhome = posix.popen('clear', 'r').read()
-    #
-    while 1:
+
+    clearhome = os.popen('clear', 'r').read()
+
+    while True:
         text = clearhome
         for name in printers:
-            text = text + makestatus(name, thisuser) + '\n'
+            text += makestatus(name, thisuser) + '\n'
         print(text)
         time.sleep(delay)
 
 def makestatus(name, thisuser):
-    pipe = posix.popen('lpq -P' + name + ' 2>&1', 'r')
+    pipe = os.popen('lpq -P' + name + ' 2>&1', 'r')
     lines = []
     users = {}
     aheadbytes = 0
     aheadjobs = 0
-    userseen = 0
+    userseen = False
     totalbytes = 0
     totaljobs = 0
-    while 1:
-        line = pipe.readline()
-        if not line: break
-        fields = string.split(line)
+    for line in pipe:
+        fields = line.split()
         n = len(fields)
         if len(fields) >= 6 and fields[n-1] == 'bytes':
-            rank = fields[0]
-            user = fields[1]
-            job = fields[2]
+            rank, user, job = fields[0:3]
             files = fields[3:-2]
-            bytes = eval(fields[n-2])
+            bytes = int(fields[n-2])
             if user == thisuser:
-                userseen = 1
+                userseen = True
             elif not userseen:
-                aheadbytes = aheadbytes + bytes
-                aheadjobs = aheadjobs + 1
-            totalbytes = totalbytes + bytes
-            totaljobs = totaljobs + 1
-            if user in users:
-                ujobs, ubytes = users[user]
-            else:
-                ujobs, ubytes = 0, 0
-            ujobs = ujobs + 1
-            ubytes = ubytes + bytes
+                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 = string.strip(line)
+                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)
+        line = '%d K' % ((totalbytes+1023) // 1024)
         if totaljobs != len(users):
-            line = line + ' (%d jobs)' % totaljobs
+            line += ' (%d jobs)' % totaljobs
         if len(users) == 1:
-            line = line + ' for %s' % (list(users.keys())[0],)
+            line += ' for %s' % next(iter(users))
         else:
-            line = line + ' for %d users' % len(users)
+            line += ' for %d users' % len(users)
             if userseen:
                 if aheadjobs == 0:
-                    line =  line + ' (%s first)' % thisuser
+                    line += ' (%s first)' % thisuser
                 else:
-                    line = line + ' (%d K before %s)' % (
-                                   (aheadbytes+1023)//1024, thisuser)
+                    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 string.joinfields(lines, ': ')
+    return ': '.join(lines)
 
 if __name__ == "__main__":
     try:

Modified: python/branches/release31-maint/Demo/scripts/markov.py
==============================================================================
--- python/branches/release31-maint/Demo/scripts/markov.py	(original)
+++ python/branches/release31-maint/Demo/scripts/markov.py	Tue Oct 27 21:19:02 2009
@@ -5,11 +5,10 @@
         self.histsize = histsize
         self.choice = choice
         self.trans = {}
+
     def add(self, state, next):
-        if state not in self.trans:
-            self.trans[state] = [next]
-        else:
-            self.trans[state].append(next)
+        self.trans.setdefault(state, []).append(next)
+
     def put(self, seq):
         n = self.histsize
         add = self.add
@@ -17,26 +16,29 @@
         for i in range(len(seq)):
             add(seq[max(0, i-n):i], seq[i:i+1])
         add(seq[len(seq)-n:], None)
+
     def get(self):
         choice = self.choice
         trans = self.trans
         n = self.histsize
         seq = choice(trans[None])
-        while 1:
+        while True:
             subseq = seq[max(0, len(seq)-n):]
             options = trans[subseq]
             next = choice(options)
-            if not next: break
-            seq = seq + next
+            if not next:
+                break
+            seq += next
         return seq
 
+
 def test():
-    import sys, string, random, getopt
+    import sys, random, getopt
     args = sys.argv[1:]
     try:
-        opts, args = getopt.getopt(args, '0123456789cdw')
+        opts, args = getopt.getopt(args, '0123456789cdwq')
     except getopt.error:
-        print('Usage: markov [-#] [-cddqw] [file] ...')
+        print('Usage: %s [-#] [-cddqw] [file] ...' % sys.argv[0])
         print('Options:')
         print('-#: 1-digit history size (default 2)')
         print('-c: characters (default)')
@@ -49,16 +51,19 @@
         print('exactly one space separating words.')
         print('Output consists of paragraphs separated by blank')
         print('lines, where lines are no longer than 72 characters.')
+        sys.exit(2)
     histsize = 2
-    do_words = 0
+    do_words = False
     debug = 1
     for o, a in opts:
-        if '-0' <= o <= '-9': histsize = eval(o[1:])
-        if o == '-c': do_words = 0
-        if o == '-d': debug = debug + 1
+        if '-0' <= o <= '-9': histsize = int(o[1:])
+        if o == '-c': do_words = False
+        if o == '-d': debug += 1
         if o == '-q': debug = 0
-        if o == '-w': do_words = 1
-    if not args: args = ['-']
+        if o == '-w': do_words = True
+    if not args:
+        args = ['-']
+
     m = Markov(histsize, random.choice)
     try:
         for filename in args:
@@ -72,13 +77,15 @@
             if debug: print('processing', filename, '...')
             text = f.read()
             f.close()
-            paralist = string.splitfields(text, '\n\n')
+            paralist = text.split('\n\n')
             for para in paralist:
                 if debug > 1: print('feeding ...')
-                words = string.split(para)
+                words = para.split()
                 if words:
-                    if do_words: data = tuple(words)
-                    else: data = string.joinfields(words, ' ')
+                    if do_words:
+                        data = tuple(words)
+                    else:
+                        data = ' '.join(words)
                     m.put(data)
     except KeyboardInterrupt:
         print('Interrupted -- continue with data read so far')
@@ -86,16 +93,19 @@
         print('No valid input files')
         return
     if debug: print('done.')
+
     if debug > 1:
         for key in m.trans.keys():
             if key is None or len(key) < histsize:
                 print(repr(key), m.trans[key])
         if histsize == 0: print(repr(''), m.trans[''])
         print()
-    while 1:
+    while True:
         data = m.get()
-        if do_words: words = data
-        else: words = string.split(data)
+        if do_words:
+            words = data
+        else:
+            words = data.split()
         n = 0
         limit = 72
         for w in words:
@@ -103,15 +113,9 @@
                 print()
                 n = 0
             print(w, end=' ')
-            n = n + len(w) + 1
+            n += len(w) + 1
         print()
         print()
 
-def tuple(list):
-    if len(list) == 0: return ()
-    if len(list) == 1: return (list[0],)
-    i = len(list)//2
-    return tuple(list[:i]) + tuple(list[i:])
-
 if __name__ == "__main__":
     test()

Deleted: python/branches/release31-maint/Demo/scripts/mkrcs.py
==============================================================================
--- python/branches/release31-maint/Demo/scripts/mkrcs.py	Tue Oct 27 21:19:02 2009
+++ (empty file)
@@ -1,61 +0,0 @@
-#! /usr/bin/env python
-
-# A rather specialized script to make sure that a symbolic link named
-# RCS exists pointing to a real RCS directory in a parallel tree
-# referenced as RCStree in an ancestor directory.
-# (I use this because I like my RCS files to reside on a physically
-# different machine).
-
-import os
-
-def main():
-    rcstree = 'RCStree'
-    rcs = 'RCS'
-    if os.path.islink(rcs):
-        print('%r is a symlink to %r' % (rcs, os.readlink(rcs)))
-        return
-    if os.path.isdir(rcs):
-        print('%r is an ordinary directory' % (rcs,))
-        return
-    if os.path.exists(rcs):
-        print('%r is a file?!?!' % (rcs,))
-        return
-    #
-    p = os.getcwd()
-    up = ''
-    down = ''
-    # Invariants:
-    # (1) join(p, down) is the current directory
-    # (2) up is the same directory as p
-    # Ergo:
-    # (3) join(up, down) is the current directory
-    #print 'p =', repr(p)
-    while not os.path.isdir(os.path.join(p, rcstree)):
-        head, tail = os.path.split(p)
-        #print 'head = %r; tail = %r' % (head, tail)
-        if not tail:
-            print('Sorry, no ancestor dir contains %r' % (rcstree,))
-            return
-        p = head
-        up = os.path.join(os.pardir, up)
-        down = os.path.join(tail, down)
-        #print 'p = %r; up = %r; down = %r' % (p, up, down)
-    there = os.path.join(up, rcstree)
-    there = os.path.join(there, down)
-    there = os.path.join(there, rcs)
-    if os.path.isdir(there):
-        print('%r already exists' % (there, ))
-    else:
-        print('making %r' % (there,))
-        makedirs(there)
-    print('making symlink %r -> %r' % (rcs, there))
-    os.symlink(there, rcs)
-
-def makedirs(p):
-    if not os.path.isdir(p):
-        head, tail = os.path.split(p)
-        makedirs(head)
-        os.mkdir(p, 0o777)
-
-if __name__ == "__main__":
-    main()

Modified: python/branches/release31-maint/Demo/scripts/newslist.py
==============================================================================
--- python/branches/release31-maint/Demo/scripts/newslist.py	(original)
+++ python/branches/release31-maint/Demo/scripts/newslist.py	Tue Oct 27 21:19:02 2009
@@ -32,22 +32,22 @@
 # fraser at europarc.xerox.com                     qs101 at cl.cam.ac.uk
 #                                                                     #
 #######################################################################
-import sys,nntplib, string, marshal, time, os, posix, string
+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='/anfs/qsbigdisc/web/html/newspage'
+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 = posix.environ['NNTPSERVER']
-newshost = 'nntp-serv.cl.cam.ac.uk'
+#    newshost = os.environ['NNTPSERVER']
+newshost = 'news.example.com'
 
 # The filename for a local cache of the newsgroup list
 treefile = 'grouptree'
@@ -81,7 +81,7 @@
 # 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"> '
+pagelinkicon = '... <img src="http://pelican.cl.cam.ac.uk/icons/page.xbm"> '
 
 # ---------------------------------------------------------------------
 # Less important personal preferences:
@@ -106,7 +106,7 @@
 from stat import *
 
 rcsrev = '$Revision$'
-rcsrev = string.join([s for s in string.split(rcsrev) if '$' not in s])
+rcsrev = ' '.join([s for s in rcsrev.split() if '$' not in s])
 desc = {}
 
 # Make (possibly) relative filenames into absolute ones
@@ -120,7 +120,7 @@
 def addtotree(tree, groups):
     print('Updating tree...')
     for i in groups:
-        parts = string.splitfields(i,'.')
+        parts = i.split('.')
         makeleaf(tree, parts)
 
 # Makeleaf makes a leaf and the branch leading to it if necessary
@@ -141,34 +141,38 @@
 # to those groups beginning with <root>.
 
 def createpage(root, tree, p):
-    filename = os.path.join(pagedir,root+'.html')
+    filename = os.path.join(pagedir, root+'.html')
     if root == rootpage:
         detail = ''
     else:
         detail = ' under ' + root
-    f = open(filename,'w')
-    # f.write('Content-Type: text/html\n')
-    f.write('<TITLE>Newsgroups available' + detail + '</TITLE>\n')
-    f.write('<H1>Newsgroups available' + detail +'</H1>\n')
-    f.write('<A HREF="'+httppref+rootpage+'.html">Back to top level</A><P>\n')
-    printtree(f,tree,0,p)
-    f.write('<I>This page automatically created by \'newslist\' v. '+rcsrev+'.')
-    f.write(time.ctime(time.time()) + '</I><P>')
-    f.close()
+    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):
-    global desc
     l = len(tree)
 
-    if l > sublistsize and indent>0:
+    if l > sublistsize and indent > 0:
         # Create a new page and a link to it
-        f.write('<LI><B><A HREF="'+httppref+p[1:]+'.html">')
-        f.write(p[1:]+'.*')
-        f.write('</A></B>'+pagelinkicon+'\n')
+        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
 
@@ -177,67 +181,64 @@
     if l > 1:
         if indent > 0:
             # Create a sub-list
-            f.write('<LI>'+p[1:]+'\n<UL>')
+            f.write('<li>%s\n<ul>' % p[1:])
         else:
             # Create a main list
-            f.write('<UL>')
+            f.write('<ul>')
         indent = indent + 1
 
     for i in kl:
         if i == '.':
             # Output a newsgroup
-            f.write('<LI><A HREF="news:' + p[1:] + '">'+ p[1:] + '</A> ')
+            f.write('<li><a href="news:%s">%s</a> ' % (p[1:], p[1:]))
             if p[1:] in desc:
-                f.write('     <I>'+desc[p[1:]]+'</I>\n')
+                f.write('     <i>%s</i>\n' % desc[p[1:]])
             else:
                 f.write('\n')
         else:
             # Output a hierarchy
-            printtree(f,tree[i], indent, p+'.'+i)
+            printtree(f, tree[i], indent, p+'.'+i)
 
     if l > 1:
-        f.write('\n</UL>')
+        f.write('\n</ul>')
 
 # Reading descriptions file ---------------------------------------
 
-# This returns an array mapping group name to its description
+# This returns a dict mapping group name to its description
 
 def readdesc(descfile):
     global desc
-
     desc = {}
 
     if descfile == '':
         return
 
     try:
-        d = open(descfile, 'r')
-        print('Reading descriptions...')
-    except (IOError):
+        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
-    l = d.readline()
-    while l != '':
-        bits = string.split(l)
-        try:
-            grp = bits[0]
-            dsc = string.join(bits[1:])
-            if len(dsc)>1:
-                desc[grp] = dsc
-        except (IndexError):
-            pass
-        l = d.readline()
 
 # Check that ouput directory exists, ------------------------------
 # and offer to create it if not
 
 def checkopdir(pagedir):
     if not os.path.isdir(pagedir):
-        print('Directory '+pagedir+' does not exist.')
+        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)
+                os.mkdir(pagedir, 0o777)
             except:
                 print('Sorry - failed!')
                 sys.exit(1)
@@ -257,23 +258,21 @@
         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])
+    treedate = '%02d%02d%02d' % (treetime[0] % 100, treetime[1], treetime[2])
     try:
-        dump = open(treefile,'r')
-        tree = marshal.load(dump)
-        dump.close()
-    except (IOError):
+        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:
-        dump = open(treefile,'w')
-        groups = marshal.dump(tree,dump)
-        dump.close()
-        print('Saved list to '+treefile+'\n')
+        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('Sorry - failed to write to local group cache', treefile)
         print('Does it (or its directory) have the correct permissions?')
         sys.exit(1)
 
@@ -281,18 +280,18 @@
 
 def getallgroups(server):
     print('Getting list of all groups...')
-    treedate='010101'
+    treedate = '010101'
     info = server.list()[1]
     groups = []
     print('Processing...')
     if skipempty:
         print('\nIgnoring following empty groups:')
     for i in info:
-        grpname = string.split(i[0])[0]
-        if skipempty and string.atoi(i[1]) < string.atoi(i[2]):
-            print(grpname+' ', end=' ')
+        grpname = i[0].split()[0]
+        if skipempty and int(i[1]) < int(i[2]):
+            print(grpname.decode() + ' ', end=' ')
         else:
-            groups.append(grpname)
+            groups.append(grpname.decode())
     print('\n')
     if skipempty:
         print('(End of empty groups)')
@@ -301,42 +300,39 @@
 # Return list of new groups on server -----------------------------
 
 def getnewgroups(server, treedate):
-    print('Getting list of new groups since start of '+treedate+'...', end=' ')
-    info = server.newgroups(treedate,'000001')[1]
+    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 = string.split(i)[0]
-        groups.append(grpname)
+        grpname = i.split()[0]
+        groups.append(grpname.decode())
     print('Done')
     return groups
 
 # Now the main program --------------------------------------------
 
 def main():
-    global desc
-
-    tree={}
+    tree = {}
 
     # Check that the output directory exists
     checkopdir(pagedir)
 
     try:
-        print('Connecting to '+newshost+'...')
+        print('Connecting to %s...' % newshost)
         if sys.version[0] == '0':
             s = NNTP.init(newshost)
         else:
             s = NNTP(newshost)
-        connected = 1
+        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 = 0
+        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

Modified: python/branches/release31-maint/Demo/scripts/pi.py
==============================================================================
--- python/branches/release31-maint/Demo/scripts/pi.py	(original)
+++ python/branches/release31-maint/Demo/scripts/pi.py	Tue Oct 27 21:19:02 2009
@@ -12,7 +12,7 @@
 
 def main():
     k, a, b, a1, b1 = 2, 4, 1, 12, 4
-    while 1:
+    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
@@ -25,7 +25,6 @@
 
 def output(d):
     # Use write() to avoid spaces between the digits
-    # Use str() to avoid the 'L'
     sys.stdout.write(str(d))
     # Flush so the output is seen immediately
     sys.stdout.flush()

Modified: python/branches/release31-maint/Demo/scripts/pp.py
==============================================================================
--- python/branches/release31-maint/Demo/scripts/pp.py	(original)
+++ python/branches/release31-maint/Demo/scripts/pp.py	Tue Oct 27 21:19:02 2009
@@ -22,7 +22,6 @@
 # - except for -n/-p, run directly from the file if at all possible
 
 import sys
-import string
 import getopt
 
 FS = ''
@@ -36,7 +35,7 @@
 try:
     optlist, ARGS = getopt.getopt(sys.argv[1:], 'acde:F:np')
 except getopt.error as msg:
-    sys.stderr.write(sys.argv[0] + ': ' + msg + '\n')
+    sys.stderr.write('%s: %s\n' % (sys.argv[0], msg))
     sys.exit(2)
 
 for option, optarg in optlist:
@@ -47,7 +46,7 @@
     elif option == '-d':
         DFLAG = 1
     elif option == '-e':
-        for line in string.splitfields(optarg, '\n'):
+        for line in optarg.split('\n'):
             SCRIPT.append(line)
     elif option == '-F':
         FS = optarg
@@ -81,31 +80,31 @@
 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 = string.splitfields(L, FS)', \
-            '   \t   \t   \telse: F = string.split(L)' \
+    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 string.joinfields(F, FS)', \
-            '   \t   \t   \telse: print string.join(F)', \
-            '   \t   \telse: print L', \
+    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:']
@@ -114,18 +113,13 @@
 # Note that we indent using tabs only, so that any indentation style
 # used in 'command' will come out right after re-indentation.
 
-program = string.joinfields(prologue, '\n') + '\n'
+program = '\n'.join(prologue) + '\n'
 for line in SCRIPT:
-    program = program + ('   \t   \t' + line + '\n')
-program = program + (string.joinfields(epilogue, '\n') + '\n')
+    program += '   \t   \t' + line + '\n'
+program += '\n'.join(epilogue) + '\n'
 
-import tempfile
-fp = tempfile.NamedTemporaryFile()
-fp.write(program)
-fp.flush()
-script = open(tfn).read()
 if DFLAG:
     import pdb
-    pdb.run(script)
+    pdb.run(program)
 else:
-    exec(script)
+    exec(program)

Modified: python/branches/release31-maint/Demo/scripts/queens.py
==============================================================================
--- python/branches/release31-maint/Demo/scripts/queens.py	(original)
+++ python/branches/release31-maint/Demo/scripts/queens.py	Tue Oct 27 21:19:02 2009
@@ -19,8 +19,8 @@
 
     def reset(self):
         n = self.n
-        self.y = [None]*n               # Where is the queen in column x
-        self.row = [0]*n                # Is row[y] safe?
+        self.y = [None] * n             # Where is the queen in column x
+        self.row = [0] * n              # Is row[y] safe?
         self.up = [0] * (2*n-1)         # Is upward diagonal[x-y] safe?
         self.down = [0] * (2*n-1)       # Is downward diagonal[x+y] safe?
         self.nfound = 0                 # Instrumentation
@@ -50,7 +50,7 @@
         self.up[x-y] = 0
         self.down[x+y] = 0
 
-    silent = 0                          # If set, count solutions only
+    silent = 0                          # If true, count solutions only
 
     def display(self):
         self.nfound = self.nfound + 1

Modified: python/branches/release31-maint/Demo/scripts/script.py
==============================================================================
--- python/branches/release31-maint/Demo/scripts/script.py	(original)
+++ python/branches/release31-maint/Demo/scripts/script.py	Tue Oct 27 21:19:02 2009
@@ -1,4 +1,5 @@
 #! /usr/bin/env python
+
 # script.py -- Make typescript of terminal session.
 # Usage:
 #       -a      Append to typescript.
@@ -6,28 +7,36 @@
 # Author: Steen Lumholt.
 
 
-import os, time, sys
+import os, time, sys, getopt
 import pty
 
 def read(fd):
     data = os.read(fd, 1024)
-    file.write(data)
+    script.write(data)
     return data
 
 shell = 'sh'
 filename = 'typescript'
-mode = 'w'
+mode = 'wb'
 if 'SHELL' in os.environ:
     shell = os.environ['SHELL']
-if '-a' in sys.argv:
-    mode = 'a'
-if '-p' in sys.argv:
-    shell = 'python'
 
-file = open(filename, mode)
+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)
-file.write('Script started on %s\n' % time.ctime(time.time()))
+script.write(('Script started on %s\n' % time.ctime(time.time())).encode())
 pty.spawn(shell, read)
-file.write('Script done on %s\n' % time.ctime(time.time()))
+script.write(('Script done on %s\n' % time.ctime(time.time())).encode())
 sys.stdout.write('Script done, file is %s\n' % filename)

Modified: python/branches/release31-maint/Demo/scripts/unbirthday.py
==============================================================================
--- python/branches/release31-maint/Demo/scripts/unbirthday.py	(original)
+++ python/branches/release31-maint/Demo/scripts/unbirthday.py	Tue Oct 27 21:19:02 2009
@@ -9,35 +9,27 @@
 import time
 import calendar
 
-def raw_input(prompt):
-    sys.stdout.write(prompt)
-    sys.stdout.flush()
-    return sys.stdin.readline()
-
 def main():
-    # Note that the range checks below also check for bad types,
-    # e.g. 3.14 or ().  However syntactically invalid replies
-    # will raise an exception.
     if sys.argv[1:]:
         year = int(sys.argv[1])
     else:
         year = int(input('In which year were you born? '))
-    if 0<=year<100:
+    if 0 <= year < 100:
         print("I'll assume that by", year, end=' ')
         year = year + 1900
         print('you mean', year, 'and not the early Christian era')
-    elif not (1850<=year<=2002):
+    elif not (1850 <= year <= time.localtime()[0]):
         print("It's hard to believe you were born in", year)
         return
-    #
+
     if sys.argv[2:]:
         month = int(sys.argv[2])
     else:
         month = int(input('And in which month? (1-12) '))
-    if not (1<=month<=12):
+    if not (1 <= month <= 12):
         print('There is no month numbered', month)
         return
-    #
+
     if sys.argv[3:]:
         day = int(sys.argv[3])
     else:
@@ -46,36 +38,36 @@
         maxday = 29
     else:
         maxday = calendar.mdays[month]
-    if not (1<=day<=maxday):
+    if not (1 <= day <= maxday):
         print('There are no', day, 'days in that month!')
         return
-    #
+
     bdaytuple = (year, month, day)
     bdaydate = mkdate(bdaytuple)
     print('You were born on', format(bdaytuple))
-    #
+
     todaytuple = time.localtime()[:3]
     todaydate = mkdate(todaytuple)
     print('Today is', format(todaytuple))
-    #
+
     if bdaytuple > todaytuple:
         print('You are a time traveler.  Go back to the future!')
         return
-    #
+
     if bdaytuple == todaytuple:
         print('You were born today.  Have a nice life!')
         return
-    #
+
     days = todaydate - bdaydate
     print('You have lived', days, 'days')
-    #
+
     age = 0
     for y in range(year, todaytuple[0] + 1):
         if bdaytuple < (y, month, day) <= todaytuple:
             age = age + 1
-    #
+
     print('You are', age, 'years old')
-    #
+
     if todaytuple[1:] == bdaytuple[1:]:
         print('Congratulations!  Today is your', nth(age), 'birthday')
         print('Yesterday was your', end=' ')
@@ -83,8 +75,8 @@
         print('Today is your', end=' ')
     print(nth(days - age), 'unbirthday')
 
-def format(xxx_todo_changeme):
-    (year, month, day) = xxx_todo_changeme
+def format(date):
+    (year, month, day) = date
     return '%d %s %d' % (day, calendar.month_name[month], year)
 
 def nth(n):
@@ -93,12 +85,12 @@
     if n == 3: return '3rd'
     return '%dth' % n
 
-def mkdate(xxx_todo_changeme1):
-    # Januari 1st, in 0 A.D. is arbitrarily defined to be day 1,
+def mkdate(date):
+    # January 1st, in 0 A.D. is arbitrarily defined to be day 1,
     # even though that day never actually existed and the calendar
     # was different then...
-    (year, month, day) = xxx_todo_changeme1
-    days = year*365                 # years, roughly
+    (year, month, day) = date
+    days = year*365                  # years, roughly
     days = days + (year+3)//4        # plus leap years, roughly
     days = days - (year+99)//100     # minus non-leap years every century
     days = days + (year+399)//400    # plus leap years every 4 centirues

Modified: python/branches/release31-maint/Demo/xml/elem_count.py
==============================================================================
--- python/branches/release31-maint/Demo/xml/elem_count.py	(original)
+++ python/branches/release31-maint/Demo/xml/elem_count.py	Tue Oct 27 21:19:02 2009
@@ -1,4 +1,10 @@
+"""
+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
 
@@ -7,16 +13,16 @@
     def __init__(self):
         self._elems = 0
         self._attrs = 0
-        self._elem_types = {}
-        self._attr_types = {}
+        self._elem_types = defaultdict(int)
+        self._attr_types = defaultdict(int)
 
     def startElement(self, name, attrs):
-        self._elems = self._elems + 1
-        self._attrs = self._attrs + len(attrs)
-        self._elem_types[name] = self._elem_types.get(name, 0) + 1
+        self._elems += 1
+        self._attrs += len(attrs)
+        self._elem_types[name] += 1
 
         for name in attrs.keys():
-            self._attr_types[name] = self._attr_types.get(name, 0) + 1
+            self._attr_types[name] += 1
 
     def endDocument(self):
         print("There were", self._elems, "elements.")
@@ -30,7 +36,7 @@
         for pair in  self._attr_types.items():
             print("%20s %d" % pair)
 
-
-parser = make_parser()
-parser.setContentHandler(FancyCounter())
-parser.parse(sys.argv[1])
+if __name__ == '__main__':
+    parser = make_parser()
+    parser.setContentHandler(FancyCounter())
+    parser.parse(sys.argv[1])

Modified: python/branches/release31-maint/Demo/xml/roundtrip.py
==============================================================================
--- python/branches/release31-maint/Demo/xml/roundtrip.py	(original)
+++ python/branches/release31-maint/Demo/xml/roundtrip.py	Tue Oct 27 21:19:02 2009
@@ -3,7 +3,7 @@
 but not necessarily identical, document.
 """
 
-import sys, string
+import sys
 
 from xml.sax import saxutils, handler, make_parser
 
@@ -11,7 +11,7 @@
 
 class ContentGenerator(handler.ContentHandler):
 
-    def __init__(self, out = sys.stdout):
+    def __init__(self, out=sys.stdout):
         handler.ContentHandler.__init__(self)
         self._out = out
 
@@ -40,6 +40,7 @@
 
 # --- The main program
 
-parser = make_parser()
-parser.setContentHandler(ContentGenerator())
-parser.parse(sys.argv[1])
+if __name__ == '__main__':
+    parser = make_parser()
+    parser.setContentHandler(ContentGenerator())
+    parser.parse(sys.argv[1])

Modified: python/branches/release31-maint/Demo/xml/rss2html.py
==============================================================================
--- python/branches/release31-maint/Demo/xml/rss2html.py	(original)
+++ python/branches/release31-maint/Demo/xml/rss2html.py	Tue Oct 27 21:19:02 2009
@@ -1,45 +1,50 @@
+"""
+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 = \
-"""
+top = """\
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<HTML>
-<HEAD>
-  <TITLE>%s</TITLE>
-</HEAD>
+<html>
+<head>
+  <title>%s</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+</head>
 
-<BODY>
-<H1>%s</H1>
+<body>
+<h1>%s</h1>
 """
 
-bottom = \
-"""
+bottom = """
 </ul>
 
-<HR>
-<ADDRESS>
-Converted to HTML by sax_rss2html.py.
-</ADDRESS>
+<hr>
+<address>
+Converted to HTML by rss2html.py.
+</address>
 
-</BODY>
-</HTML>
+</body>
+</html>
 """
 
 # --- The ContentHandler
 
 class RSSHandler(handler.ContentHandler):
 
-    def __init__(self, out = sys.stdout):
+    def __init__(self, out=sys.stdout):
         handler.ContentHandler.__init__(self)
         self._out = out
 
         self._text = ""
         self._parent = None
-        self._list_started = 0
+        self._list_started = False
         self._title = None
         self._link = None
         self._descr = ""
@@ -69,7 +74,7 @@
             elif name == "item":
                 if not self._list_started:
                     self._out.write("<ul>\n")
-                    self._list_started = 1
+                    self._list_started = True
 
                 self._out.write('  <li><a href="%s">%s</a> %s\n' %
                                 (self._link, self._title, self._descr))
@@ -86,6 +91,7 @@
 
 # --- Main program
 
-parser = make_parser()
-parser.setContentHandler(RSSHandler())
-parser.parse(sys.argv[1])
+if __name__ == '__main__':
+    parser = make_parser()
+    parser.setContentHandler(RSSHandler())
+    parser.parse(sys.argv[1])

Modified: python/branches/release31-maint/Doc/library/configparser.rst
==============================================================================
--- python/branches/release31-maint/Doc/library/configparser.rst	(original)
+++ python/branches/release31-maint/Doc/library/configparser.rst	Tue Oct 27 21:19:02 2009
@@ -231,9 +231,11 @@
 .. method:: RawConfigParser.readfp(fp, filename=None)
 
    Read and parse configuration data from the file or file-like object in *fp*
-   (only the :meth:`readline` method is used).  If *filename* is omitted and *fp*
-   has a :attr:`name` attribute, that is used for *filename*; the default is
-   ``<???>``.
+   (only the :meth:`readline` method is used).  The file-like object must
+   operate in text mode, i.e. return strings from :meth:`readline`.
+
+   If *filename* is omitted and *fp* has a :attr:`name` attribute, that is used
+   for *filename*; the default is ``<???>``.
 
 
 .. method:: RawConfigParser.get(section, option)
@@ -279,8 +281,9 @@
 
 .. method:: RawConfigParser.write(fileobject)
 
-   Write a representation of the configuration to the specified file object.  This
-   representation can be parsed by a future :meth:`read` call.
+   Write a representation of the configuration to the specified file object,
+   which must be opened in text mode (accepting strings).  This representation
+   can be parsed by a future :meth:`read` call.
 
 
 .. method:: RawConfigParser.remove_option(section, option)
@@ -370,7 +373,7 @@
    config.set('Section1', 'foo', '%(bar)s is %(baz)s!')
 
    # Writing our configuration file to 'example.cfg'
-   with open('example.cfg', 'wb') as configfile:
+   with open('example.cfg', 'w') as configfile:
        config.write(configfile)
 
 An example of reading the configuration file again::

Modified: python/branches/release31-maint/Doc/library/copy.rst
==============================================================================
--- python/branches/release31-maint/Doc/library/copy.rst	(original)
+++ python/branches/release31-maint/Doc/library/copy.rst	Tue Oct 27 21:19:02 2009
@@ -4,21 +4,25 @@
 .. module:: copy
    :synopsis: Shallow and deep copy operations.
 
+This module provides generic (shallow and deep) copying operations.
 
-.. index::
-   single: copy() (in copy)
-   single: deepcopy() (in copy)
 
-This module provides generic (shallow and deep) copying operations.
+Interface summary:
+
+.. function:: copy(x)
+
+   Return a shallow copy of *x*.
+
+
+.. function:: deepcopy(x)
+
+   Return a deep copy of *x*.
 
-Interface summary::
 
-   import copy
+.. exception:: error
 
-   x = copy.copy(y)        # make a shallow copy of y
-   x = copy.deepcopy(y)    # make a deep copy of y
+   Raised for module specific errors.
 
-For module specific errors, :exc:`copy.error` is raised.
 
 The difference between shallow and deep copying is only relevant for compound
 objects (objects that contain other objects, like lists or class instances):

Modified: python/branches/release31-maint/Doc/library/marshal.rst
==============================================================================
--- python/branches/release31-maint/Doc/library/marshal.rst	(original)
+++ python/branches/release31-maint/Doc/library/marshal.rst	Tue Oct 27 21:19:02 2009
@@ -36,12 +36,14 @@
 
 Not all Python object types are supported; in general, only objects whose value
 is independent from a particular invocation of Python can be written and read by
-this module.  The following types are supported: ``None``, integers,
-floating point numbers, strings, bytes, bytearrays, tuples, lists, sets,
-dictionaries, and code objects, where it should be understood that tuples, lists
-and dictionaries are only supported as long as the values contained therein are
-themselves supported; and recursive lists and dictionaries should not be written
-(they will cause infinite loops).
+this module.  The following types are supported: booleans, integers, floating
+point numbers, complex numbers, strings, bytes, bytearrays, tuples, lists, sets,
+frozensets, dictionaries, and code objects, where it should be understood that
+tuples, lists, sets, frozensets and dictionaries are only supported as long as
+the values contained therein are themselves supported; and recursive lists, sets
+and dictionaries should not be written (they will cause infinite loops).  The
+singletons :const:`None`, :const:`Ellipsis` and :exc:`StopIteration` can also be
+marshalled and unmarshalled.
 
 There are functions that read/write files as well as functions operating on
 strings.

Modified: python/branches/release31-maint/Doc/library/urllib.parse.rst
==============================================================================
--- python/branches/release31-maint/Doc/library/urllib.parse.rst	(original)
+++ python/branches/release31-maint/Doc/library/urllib.parse.rst	Tue Oct 27 21:19:02 2009
@@ -227,7 +227,8 @@
 .. function:: quote(string, safe='/', encoding=None, errors=None)
 
    Replace special characters in *string* using the ``%xx`` escape. Letters,
-   digits, and the characters ``'_.-'`` are never quoted. The optional *safe*
+   digits, and the characters ``'_.-'`` are never quoted. By default, this
+   function is intended for quoting the path section of URL. The optional *safe*
    parameter specifies additional ASCII characters that should not be quoted
    --- its default value is ``'/'``.
 

Modified: python/branches/release31-maint/Doc/reference/datamodel.rst
==============================================================================
--- python/branches/release31-maint/Doc/reference/datamodel.rst	(original)
+++ python/branches/release31-maint/Doc/reference/datamodel.rst	Tue Oct 27 21:19:02 2009
@@ -666,7 +666,7 @@
    of the shared library file.
 
 Custom classes
-   Custon class types are typically created by class definitions (see section
+   Custom class types are typically created by class definitions (see section
    :ref:`class`).  A class has a namespace implemented by a dictionary object.
    Class attribute references are translated to lookups in this dictionary, e.g.,
    ``C.x`` is translated to ``C.__dict__["x"]`` (although there are a number of

Modified: python/branches/release31-maint/Lib/pdb.py
==============================================================================
--- python/branches/release31-maint/Lib/pdb.py	(original)
+++ python/branches/release31-maint/Lib/pdb.py	Tue Oct 27 21:19:02 2009
@@ -208,7 +208,9 @@
         """Custom displayhook for the exec in default(), which prevents
         assignment of the _ variable in the builtins.
         """
-        print(repr(obj))
+        # reproduce the behavior of the standard displayhook, not printing None
+        if obj is not None:
+            print(repr(obj))
 
     def default(self, line):
         if line[:1] == '!': line = line[1:]

Modified: python/branches/release31-maint/Lib/pydoc.py
==============================================================================
--- python/branches/release31-maint/Lib/pydoc.py	(original)
+++ python/branches/release31-maint/Lib/pydoc.py	Tue Oct 27 21:19:02 2009
@@ -1557,7 +1557,7 @@
         'global': ('global', 'NAMESPACES'),
         'if': ('if', 'TRUTHVALUE'),
         'import': ('import', 'MODULES'),
-        'in': ('in', 'SEQUENCEMETHODS2'),
+        'in': ('in', 'SEQUENCEMETHODS'),
         'is': 'COMPARISON',
         'lambda': ('lambda', 'FUNCTIONS'),
         'not': 'BOOLEAN',
@@ -1643,12 +1643,12 @@
         'PRECEDENCE': 'EXPRESSIONS',
         'OBJECTS': ('objects', 'TYPES'),
         'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
-                           'CALLABLEMETHODS SEQUENCEMETHODS1 MAPPINGMETHODS '
-                           'SEQUENCEMETHODS2 NUMBERMETHODS CLASSES'),
+                           'CALLABLEMETHODS SEQUENCEMETHODS MAPPINGMETHODS '
+                           'NUMBERMETHODS CLASSES'),
         'BASICMETHODS': ('customization', 'hash repr str SPECIALMETHODS'),
         'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
         'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
-        'SEQUENCEMETHODS': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS2 '
+        'SEQUENCEMETHODS': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS '
                              'SPECIALMETHODS'),
         'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
         'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
@@ -1672,8 +1672,8 @@
         'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
         'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
         'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr ATTRIBUTEMETHODS'),
-        'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS1'),
-        'SLICINGS': ('slicings', 'SEQUENCEMETHODS2'),
+        'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS'),
+        'SLICINGS': ('slicings', 'SEQUENCEMETHODS'),
         'CALLS': ('calls', 'EXPRESSIONS'),
         'POWER': ('power', 'EXPRESSIONS'),
         'UNARY': ('unary', 'EXPRESSIONS'),

Modified: python/branches/release31-maint/Lib/test/test_funcattrs.py
==============================================================================
--- python/branches/release31-maint/Lib/test/test_funcattrs.py	(original)
+++ python/branches/release31-maint/Lib/test/test_funcattrs.py	Tue Oct 27 21:19:02 2009
@@ -56,8 +56,29 @@
         self.assertEqual(test(), 3) # self.b always returns 3, arbitrarily
 
     def test___globals__(self):
-        self.assertEqual(self.b.__globals__, globals())
-        self.cannot_set_attr(self.b, '__globals__', 2, (AttributeError, TypeError))
+        self.assertIs(self.b.__globals__, globals())
+        self.cannot_set_attr(self.b, '__globals__', 2,
+                             (AttributeError, TypeError))
+
+    def test___closure__(self):
+        a = 12
+        def f(): print(a)
+        c = f.__closure__
+        self.assertTrue(isinstance(c, tuple))
+        self.assertEqual(len(c), 1)
+        # don't have a type object handy
+        self.assertEqual(c[0].__class__.__name__, "cell")
+        self.cannot_set_attr(f, "__closure__", c, AttributeError)
+
+    def test_empty_cell(self):
+        def f(): print(a)
+        try:
+            f.__closure__[0].cell_contents
+        except ValueError:
+            pass
+        else:
+            self.fail("shouldn't be able to read an empty cell")
+        a = 12
 
     def test___name__(self):
         self.assertEqual(self.b.__name__, 'b')
@@ -90,16 +111,20 @@
         self.assertEqual(c.__code__, d.__code__)
         self.assertEqual(c(), 7)
         # self.assertEqual(d(), 7)
-        try: b.__code__ = c.__code__
-        except ValueError: pass
-        else: self.fail(
-            "__code__ with different numbers of free vars should not be "
-            "possible")
-        try: e.__code__ = d.__code__
-        except ValueError: pass
-        else: self.fail(
-            "__code__ with different numbers of free vars should not be "
-            "possible")
+        try:
+            b.__code__ = c.__code__
+        except ValueError:
+            pass
+        else:
+            self.fail("__code__ with different numbers of free vars should "
+                      "not be possible")
+        try:
+            e.__code__ = d.__code__
+        except ValueError:
+            pass
+        else:
+            self.fail("__code__ with different numbers of free vars should "
+                      "not be possible")
 
     def test_blank_func_defaults(self):
         self.assertEqual(self.b.__defaults__, None)
@@ -120,13 +145,16 @@
         self.assertEqual(first_func(3, 5), 8)
         del second_func.__defaults__
         self.assertEqual(second_func.__defaults__, None)
-        try: second_func()
-        except TypeError: pass
-        else: self.fail(
-            "func_defaults does not update; deleting it does not remove "
-            "requirement")
+        try:
+            second_func()
+        except TypeError:
+            pass
+        else:
+            self.fail("__defaults__ does not update; deleting it does not "
+                      "remove requirement")
 
-class ImplicitReferencesTest(FuncAttrsTest):
+
+class InstancemethodAttrTest(FuncAttrsTest):
 
     def test___class__(self):
         self.assertEqual(self.fi.a.__self__.__class__, self.F)
@@ -146,31 +174,45 @@
         self.fi.id = types.MethodType(id, self.fi)
         self.assertEqual(self.fi.id(), id(self.fi))
         # Test usage
-        try: self.fi.id.unknown_attr
-        except AttributeError: pass
-        else: self.fail("using unknown attributes should raise AttributeError")
+        try:
+            self.fi.id.unknown_attr
+        except AttributeError:
+            pass
+        else:
+            self.fail("using unknown attributes should raise AttributeError")
         # Test assignment and deletion
         self.cannot_set_attr(self.fi.id, 'unknown_attr', 2, AttributeError)
 
+
 class ArbitraryFunctionAttrTest(FuncAttrsTest):
     def test_set_attr(self):
         self.b.known_attr = 7
         self.assertEqual(self.b.known_attr, 7)
-        try: self.fi.a.known_attr = 7
-        except AttributeError: pass
-        else: self.fail("setting attributes on methods should raise error")
+        try:
+            self.fi.a.known_attr = 7
+        except AttributeError:
+            pass
+        else:
+            self.fail("setting attributes on methods should raise error")
 
     def test_delete_unknown_attr(self):
-        try: del self.b.unknown_attr
-        except AttributeError: pass
-        else: self.fail("deleting unknown attribute should raise TypeError")
+        try:
+            del self.b.unknown_attr
+        except AttributeError:
+            pass
+        else:
+            self.fail("deleting unknown attribute should raise TypeError")
 
     def test_unset_attr(self):
         for func in [self.b, self.fi.a]:
-            try:  func.non_existent_attr
-            except AttributeError: pass
-            else: self.fail("using unknown attributes should raise "
-                            "AttributeError")
+            try:
+                func.non_existent_attr
+            except AttributeError:
+                pass
+            else:
+                self.fail("using unknown attributes should raise "
+                          "AttributeError")
+
 
 class FunctionDictsTest(FuncAttrsTest):
     def test_setting_dict_to_invalid(self):
@@ -183,11 +225,11 @@
         d = {'known_attr': 7}
         self.b.__dict__ = d
         # Test assignment
-        self.assertEqual(d, self.b.__dict__)
+        self.assertIs(d, self.b.__dict__)
         # ... and on all the different ways of referencing the method's func
         self.F.a.__dict__ = d
-        self.assertEqual(d, self.fi.a.__func__.__dict__)
-        self.assertEqual(d, self.fi.a.__dict__)
+        self.assertIs(d, self.fi.a.__func__.__dict__)
+        self.assertIs(d, self.fi.a.__dict__)
         # Test value
         self.assertEqual(self.b.known_attr, 7)
         self.assertEqual(self.b.__dict__['known_attr'], 7)
@@ -196,9 +238,12 @@
         self.assertEqual(self.fi.a.known_attr, 7)
 
     def test_delete___dict__(self):
-        try: del self.b.__dict__
-        except TypeError: pass
-        else: self.fail("deleting function dictionary should raise TypeError")
+        try:
+            del self.b.__dict__
+        except TypeError:
+            pass
+        else:
+            self.fail("deleting function dictionary should raise TypeError")
 
     def test_unassigned_dict(self):
         self.assertEqual(self.b.__dict__, {})
@@ -209,6 +254,7 @@
         d[self.b] = value
         self.assertEqual(d[self.b], value)
 
+
 class FunctionDocstringTest(FuncAttrsTest):
     def test_set_docstring_attr(self):
         self.assertEqual(self.b.__doc__, None)
@@ -224,6 +270,7 @@
         del self.b.__doc__
         self.assertEqual(self.b.__doc__, None)
 
+
 def cell(value):
     """Create a cell containing the given value."""
     def f():
@@ -242,6 +289,7 @@
         a = 1729
     return f.__closure__[0]
 
+
 class CellTest(unittest.TestCase):
     def test_comparison(self):
         # These tests are here simply to exercise the comparison code;
@@ -254,6 +302,7 @@
         self.assertTrue(cell(-36) == cell(-36.0))
         self.assertTrue(cell(True) > empty_cell())
 
+
 class StaticMethodAttrsTest(unittest.TestCase):
     def test_func_attribute(self):
         def f():
@@ -267,7 +316,7 @@
 
 
 def test_main():
-    support.run_unittest(FunctionPropertiesTest, ImplicitReferencesTest,
+    support.run_unittest(FunctionPropertiesTest, InstancemethodAttrTest,
                               ArbitraryFunctionAttrTest, FunctionDictsTest,
                               FunctionDocstringTest, CellTest,
                               StaticMethodAttrsTest)

Modified: python/branches/release31-maint/Lib/test/test_pdb.py
==============================================================================
--- python/branches/release31-maint/Lib/test/test_pdb.py	(original)
+++ python/branches/release31-maint/Lib/test/test_pdb.py	Tue Oct 27 21:19:02 2009
@@ -12,6 +12,49 @@
 from test.test_doctest import _FakeInput
 
 
+class PdbTestInput(object):
+    """Context manager that makes testing Pdb in doctests easier."""
+
+    def __init__(self, input):
+        self.input = input
+
+    def __enter__(self):
+        self.real_stdin = sys.stdin
+        sys.stdin = _FakeInput(self.input)
+
+    def __exit__(self, *exc):
+        sys.stdin = self.real_stdin
+
+
+def test_pdb_displayhook():
+    """This tests the custom displayhook for pdb.
+
+    >>> def test_function(foo, bar):
+    ...     import pdb; pdb.Pdb().set_trace()
+    ...     pass
+
+    >>> with PdbTestInput([
+    ...     'foo',
+    ...     'bar',
+    ...     'for i in range(5): print(i)',
+    ...     'continue',
+    ... ]):
+    ...     test_function(1, None)
+    > <doctest test.test_pdb.test_pdb_displayhook[0]>(3)test_function()
+    -> pass
+    (Pdb) foo
+    1
+    (Pdb) bar
+    (Pdb) for i in range(5): print(i)
+    0
+    1
+    2
+    3
+    4
+    (Pdb) continue
+    """
+
+
 def test_pdb_skip_modules():
     """This illustrates the simple case of module skipping.
 
@@ -19,16 +62,12 @@
     ...     import string
     ...     import pdb; pdb.Pdb(skip=['stri*']).set_trace()
     ...     string.capwords('FOO')
-    >>> real_stdin = sys.stdin
-    >>> sys.stdin = _FakeInput([
-    ...    'step',
-    ...    'continue',
-    ...    ])
 
-    >>> try:
+    >>> with PdbTestInput([
+    ...     'step',
+    ...     'continue',
+    ... ]):
     ...     skip_module()
-    ... finally:
-    ...     sys.stdin = real_stdin
     > <doctest test.test_pdb.test_pdb_skip_modules[0]>(4)skip_module()
     -> string.capwords('FOO')
     (Pdb) step
@@ -36,7 +75,7 @@
     > <doctest test.test_pdb.test_pdb_skip_modules[0]>(4)skip_module()->None
     -> string.capwords('FOO')
     (Pdb) continue
-"""
+    """
 
 
 # Module for testing skipping of module that makes a callback
@@ -50,22 +89,19 @@
     >>> def skip_module():
     ...     def callback():
     ...         return None
-    ...     import pdb;pdb.Pdb(skip=['module_to_skip*']).set_trace()
+    ...     import pdb; pdb.Pdb(skip=['module_to_skip*']).set_trace()
     ...     mod.foo_pony(callback)
-    >>> real_stdin = sys.stdin
-    >>> sys.stdin = _FakeInput([
-    ...    'step',
-    ...    'step',
-    ...    'step',
-    ...    'step',
-    ...    'step',
-    ...    'continue',
-    ...    ])
 
-    >>> try:
+    >>> with PdbTestInput([
+    ...     'step',
+    ...     'step',
+    ...     'step',
+    ...     'step',
+    ...     'step',
+    ...     'continue',
+    ... ]):
     ...     skip_module()
-    ... finally:
-    ...     sys.stdin = real_stdin
+    ...     pass  # provides something to "step" to
     > <doctest test.test_pdb.test_pdb_skip_modules_with_callback[0]>(5)skip_module()
     -> mod.foo_pony(callback)
     (Pdb) step
@@ -84,10 +120,10 @@
     > <doctest test.test_pdb.test_pdb_skip_modules_with_callback[0]>(5)skip_module()->None
     -> mod.foo_pony(callback)
     (Pdb) step
-    > <doctest test.test_pdb.test_pdb_skip_modules_with_callback[3]>(4)<module>()
-    -> sys.stdin = real_stdin
+    > <doctest test.test_pdb.test_pdb_skip_modules_with_callback[1]>(10)<module>()
+    -> pass  # provides something to "step" to
     (Pdb) continue
-"""
+    """
 
 
 def test_main():


More information about the Python-checkins mailing list