[Python-checkins] CVS: python/dist/src/Lib quopri.py,1.5,1.6 random.py,1.12,1.13 regex_syntax.py,1.2,1.3 regsub.py,1.6,1.7 repr.py,1.5,1.6 sgmllib.py,1.18,1.19 shlex.py,1.4,1.5 shutil.py,1.14,1.15 stat.py,1.6,1.7 statcache.py,1.5,1.6 statvfs.py,1.3,1.4 string.py,1.45,1.46 sunau.py,1.14,1.15 sunaudio.py,1.3,1.4 symbol.py,1.8,1.9 tempfile.py,1.19,1.20 threading.py,1.5,1.6 toaiff.py,1.4,1.5 token.py,1.6,1.7 traceback.py,1.13,1.14 tty.py,1.1,1.2 types.py,1.12,1.13 tzparse.py,1.6,1.7 urllib.py,1.90,1.91 urllib2.py,1.1,1.2 urlparse.py,1.21,1.22 uu.py,1.10,1.11 wave.py,1.8,1.9 whrandom.py,1.14,1.15

Guido van Rossum guido@cnri.reston.va.us
Fri, 4 Feb 2000 10:28:48 -0500 (EST)


Update of /projects/cvsroot/python/dist/src/Lib
In directory eric:/projects/python/develop/guido/src/Lib

Modified Files:
	quopri.py random.py regex_syntax.py regsub.py repr.py 
	sgmllib.py shlex.py shutil.py stat.py statcache.py statvfs.py 
	string.py sunau.py sunaudio.py symbol.py tempfile.py 
	threading.py toaiff.py token.py traceback.py tty.py types.py 
	tzparse.py urllib.py urllib2.py urlparse.py uu.py wave.py 
	whrandom.py 
Log Message:
The third and final doc-string sweep by Ka-Ping Yee.

The attached patches update the standard library so that all modules
have docstrings beginning with one-line summaries.

A new docstring was added to formatter.  The docstring for os.py
was updated to mention nt, os2, ce in addition to posix, dos, mac.



Index: quopri.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/quopri.py,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -r1.5 -r1.6
*** quopri.py	1998/03/26 20:52:26	1.5
--- quopri.py	2000/02/04 15:28:40	1.6
***************
*** 1,5 ****
  #! /usr/bin/env python
  
! # Conversions to/from quoted-printable transport encoding as per RFC-1521
  # (Dec 1991 version).
  
--- 1,6 ----
  #! /usr/bin/env python
  
! """Conversions to/from quoted-printable transport encoding as per RFC-1521."""
! 
  # (Dec 1991 version).
  
***************
*** 9,12 ****
--- 10,16 ----
  
  def needsquoting(c, quotetabs):
+ 	"""Decide whether a particular character needs to be quoted.
+ 
+ 	The 'quotetabs' flag indicates whether tabs should be quoted."""
  	if c == '\t':
  		return not quotetabs
***************
*** 14,17 ****
--- 18,22 ----
  
  def quote(c):
+ 	"""Quote a single character."""
  	if c == ESCAPE:
  		return ESCAPE * 2
***************
*** 21,24 ****
--- 26,33 ----
  
  def encode(input, output, quotetabs):
+ 	"""Read 'input', apply quoted-printable encoding, and write to 'output'.
+ 
+ 	'input' and 'output' are files with readline() and write() methods.
+ 	The 'quotetabs' flag indicates whether tabs should be quoted."""
  	while 1:
  		line = input.readline()
***************
*** 43,46 ****
--- 52,58 ----
  
  def decode(input, output):
+ 	"""Read 'input', apply quoted-printable decoding, and write to 'output'.
+ 
+ 	'input' and 'output' are files with readline() and write() methods."""
  	new = ''
  	while 1:
***************
*** 74,80 ****
--- 86,94 ----
  
  def ishex(c):
+ 	"""Return true if the character 'c' is a hexadecimal digit."""
  	return '0' <= c <= '9' or 'a' <= c <= 'f' or 'A' <= c <= 'F'
  
  def unhex(s):
+ 	"""Get the integer value of a hexadecimal number."""
  	bits = 0
  	for c in s:

Index: random.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/random.py,v
retrieving revision 1.12
retrieving revision 1.13
diff -C2 -r1.12 -r1.13
*** random.py	1999/08/18 13:53:28	1.12
--- random.py	2000/02/04 15:28:40	1.13
***************
*** 1,22 ****
! #	R A N D O M   V A R I A B L E   G E N E R A T O R S
! #
! #	distributions on the real line:
! #	------------------------------
! #	       normal (Gaussian)
! #	       lognormal
! #	       negative exponential
! #	       gamma
! #	       beta
! #
! #	distributions on the circle (angles 0 to 2pi)
! #	---------------------------------------------
! #	       circular uniform
! #	       von Mises
  
! # Translated from anonymously contributed C/C++ source.
  
! # Multi-threading note: the random number generator used here is not
! # thread-safe; it is possible that two calls return the same random
! # value.  See whrandom.py for more info.
  
  import whrandom
--- 1,23 ----
! """Random variable generators.
  
!     distributions on the real line:
!     ------------------------------
!            normal (Gaussian)
!            lognormal
!            negative exponential
!            gamma
!            beta
  
!     distributions on the circle (angles 0 to 2pi)
!     ---------------------------------------------
!            circular uniform
!            von Mises
! 
! Translated from anonymously contributed C/C++ source.
! 
! Multi-threading note: the random number generator used here is not
! thread-safe; it is possible that two calls return the same random
! value.  See whrandom.py for more info.
! """
  
  import whrandom

Index: regex_syntax.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/regex_syntax.py,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -r1.2 -r1.3
*** regex_syntax.py	1997/10/22 16:28:53	1.2
--- regex_syntax.py	2000/02/04 15:28:40	1.3
***************
*** 1,4 ****
! # These bits are passed to regex.set_syntax() to choose among
! # alternative regexp syntaxes.
  
  # 1 means plain parentheses serve as grouping, and backslash
--- 1,10 ----
! """Constants for selecting regexp syntaxes for the obsolete regex module.
! 
! This module is only for backward compatibility.  "regex" has now
! been replaced by the new regular expression module, "re".
! 
! These bits are passed to regex.set_syntax() to choose among
! alternative regexp syntaxes.
! """
  
  # 1 means plain parentheses serve as grouping, and backslash

Index: regsub.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/regsub.py,v
retrieving revision 1.6
retrieving revision 1.7
diff -C2 -r1.6 -r1.7
*** regsub.py	1997/02/18 18:52:55	1.6
--- regsub.py	2000/02/04 15:28:40	1.7
***************
*** 1,9 ****
! # Regular expression subroutines:
! # sub(pat, repl, str): replace first occurrence of pattern in string
! # gsub(pat, repl, str): replace all occurrences of pattern in string
! # split(str, pat, maxsplit): split string using pattern as delimiter
! # splitx(str, pat, maxsplit): split string using pattern as delimiter plus
! #			      return delimiters
  
  
  import regex
--- 1,13 ----
! """Regexp-based split and replace using the obsolete regex module.
  
+ This module is only for backward compatibility.  These operations
+ are now provided by the new regular expression module, "re".
+ 
+ sub(pat, repl, str):        replace first occurrence of pattern in string
+ gsub(pat, repl, str):       replace all occurrences of pattern in string
+ split(str, pat, maxsplit):  split string using pattern as delimiter
+ splitx(str, pat, maxsplit): split string using pattern as delimiter plus
+                             return delimiters
+ """
  
  import regex

Index: repr.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/repr.py,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -r1.5 -r1.6
*** repr.py	1999/06/23 23:27:05	1.5
--- repr.py	2000/02/04 15:28:40	1.6
***************
*** 1,3 ****
! # Redo the `...` (representation) but with limits on most sizes.
  
  import string
--- 1,3 ----
! """Redo the `...` (representation) but with limits on most sizes."""
  
  import string

Index: sgmllib.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/sgmllib.py,v
retrieving revision 1.18
retrieving revision 1.19
diff -C2 -r1.18 -r1.19
*** sgmllib.py	1999/01/25 21:57:07	1.18
--- sgmllib.py	2000/02/04 15:28:40	1.19
***************
*** 1,3 ****
! # A parser for SGML, using the derived class as static DTD.
  
  # XXX This only supports those SGML features used by HTML.
--- 1,3 ----
! """A parser for SGML, using the derived class as a static DTD."""
  
  # XXX This only supports those SGML features used by HTML.

Index: shlex.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/shlex.py,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -r1.4 -r1.5
*** shlex.py	1999/05/03 18:14:16	1.4
--- shlex.py	2000/02/04 15:28:40	1.5
***************
*** 1,2 ****
--- 1,4 ----
+ """A lexical analyzer class for simple shell-like syntaxes."""
+ 
  # Module and documentation by Eric S. Raymond, 21 Dec 1998 
  

Index: shutil.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/shutil.py,v
retrieving revision 1.14
retrieving revision 1.15
diff -C2 -r1.14 -r1.15
*** shutil.py	1999/08/18 20:03:17	1.14
--- shutil.py	2000/02/04 15:28:41	1.15
***************
*** 1,3 ****
! """Utility functions for copying files.
  
  XXX The functions here don't copy the resource fork or other metadata on Mac.
--- 1,3 ----
! """Utility functions for copying files and directory trees.
  
  XXX The functions here don't copy the resource fork or other metadata on Mac.

Index: stat.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/stat.py,v
retrieving revision 1.6
retrieving revision 1.7
diff -C2 -r1.6 -r1.7
*** stat.py	1994/08/23 13:32:17	1.6
--- stat.py	2000/02/04 15:28:41	1.7
***************
*** 1,9 ****
! # Module 'stat'
! #
! # Defines constants and functions for interpreting stat/lstat struct
! # as returned by os.stat() and os.lstat() (if it exists).
! #
! # Suggested usage: from stat import *
! #
  # XXX Strictly spoken, this module may have to be adapted for each POSIX
  # implementation; in practice, however, the numeric constants used by
--- 1,7 ----
! """Constants/functions for interpreting results of os.stat() and os.lstat().
! 
! Suggested usage: from stat import *
! """
! 
  # XXX Strictly spoken, this module may have to be adapted for each POSIX
  # implementation; in practice, however, the numeric constants used by

Index: statcache.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/statcache.py,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -r1.5 -r1.6
*** statcache.py	1995/12/07 10:16:45	1.5
--- statcache.py	2000/02/04 15:28:41	1.6
***************
*** 1,6 ****
! # Module 'statcache'
! #
! # Maintain a cache of file stats.
! # There are functions to reset the cache or to selectively remove items.
  
  import os
--- 1,5 ----
! """Maintain a cache of file stats.
! There are functions to reset the cache or to selectively remove items.
! """
  
  import os
***************
*** 13,19 ****
  
  
- # Stat a file, possibly out of the cache.
- #
  def stat(path):
  	if cache.has_key(path):
  		return cache[path]
--- 12,17 ----
  
  
  def stat(path):
+ 	"""Stat a file, possibly out of the cache."""
  	if cache.has_key(path):
  		return cache[path]
***************
*** 22,42 ****
  
  
- # Reset the cache completely.
- #
  def reset():
  	global cache
  	cache = {}
  
  
- # Remove a given item from the cache, if it exists.
- #
  def forget(path):
  	if cache.has_key(path):
  		del cache[path]
  
  
- # Remove all pathnames with a given prefix.
- #
  def forget_prefix(prefix):
  	n = len(prefix)
  	for path in cache.keys():
--- 20,37 ----
  
  
  def reset():
+ 	"""Reset the cache completely."""
  	global cache
  	cache = {}
  
  
  def forget(path):
+ 	"""Remove a given item from the cache, if it exists."""
  	if cache.has_key(path):
  		del cache[path]
  
  
  def forget_prefix(prefix):
+ 	"""Remove all pathnames with a given prefix."""
  	n = len(prefix)
  	for path in cache.keys():
***************
*** 45,52 ****
  
  
- # Forget about a directory and all entries in it, but not about
- # entries in subdirectories.
- #
  def forget_dir(prefix):
  	if prefix[-1:] == '/' and prefix <> '/':
  		prefix = prefix[:-1]
--- 40,46 ----
  
  
  def forget_dir(prefix):
+ 	"""Forget about a directory and all entries in it, but not about
+ 	entries in subdirectories."""
  	if prefix[-1:] == '/' and prefix <> '/':
  		prefix = prefix[:-1]
***************
*** 63,70 ****
  
  
- # Remove all pathnames except with a given prefix.
- # Normally used with prefix = '/' after a chdir().
- #
  def forget_except_prefix(prefix):
  	n = len(prefix)
  	for path in cache.keys():
--- 57,63 ----
  
  
  def forget_except_prefix(prefix):
+ 	"""Remove all pathnames except with a given prefix.
+ 	Normally used with prefix = '/' after a chdir()."""
  	n = len(prefix)
  	for path in cache.keys():
***************
*** 73,79 ****
  
  
- # Check for directory.
- #
  def isdir(path):
  	try:
  		st = stat(path)
--- 66,71 ----
  
  
  def isdir(path):
+ 	"""Check for directory."""
  	try:
  		st = stat(path)

Index: statvfs.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/statvfs.py,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -r1.3 -r1.4
*** statvfs.py	1999/02/10 13:12:07	1.3
--- statvfs.py	2000/02/04 15:28:41	1.4
***************
*** 1,7 ****
! # Module 'statvfs'
! #
! # Defines constants for interpreting statvfs struct as returned
! # by os.statvfs() and os.fstatvfs() (if they exist).
! #
  
  # Indices for statvfs struct members in the tuple returned by
--- 1,3 ----
! """Constants for interpreting the results of os.statvfs() and os.fstatvfs()."""
  
  # Indices for statvfs struct members in the tuple returned by

Index: string.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/string.py,v
retrieving revision 1.45
retrieving revision 1.46
diff -C2 -r1.45 -r1.46
*** string.py	1999/11/04 19:18:44	1.45
--- string.py	2000/02/04 15:28:41	1.46
***************
*** 1,10 ****
! # module 'string' -- A collection of string operations
  
! # Warning: most of the code you see here isn't normally used nowadays.  With
! # Python 1.6, many of these functions are implemented as methods on the
! # standard string object. They used to be implemented by a built-in module
! # called strop, but strop is now obsolete itself.
! 
! """Common string manipulations.
  
  Public module variables:
--- 1,8 ----
! """A collection of string operations (most are no longer used in Python 1.6).
  
! Warning: most of the code you see here isn't normally used nowadays.  With
! Python 1.6, many of these functions are implemented as methods on the
! standard string object. They used to be implemented by a built-in module
! called strop, but strop is now obsolete itself.
  
  Public module variables:

Index: sunau.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/sunau.py,v
retrieving revision 1.14
retrieving revision 1.15
diff -C2 -r1.14 -r1.15
*** sunau.py	1999/06/22 21:23:23	1.14
--- sunau.py	2000/02/04 15:28:41	1.15
***************
*** 1,105 ****
! # Stuff to parse Sun and NeXT audio files.
! #
! # An audio consists of a header followed by the data.  The structure
! # of the header is as follows.
! #
! #	+---------------+
! #	| magic word    |
! #	+---------------+
! #	| header size   |
! #	+---------------+
! #	| data size     |
! #	+---------------+
! #	| encoding      |
! #	+---------------+
! #	| sample rate   |
! #	+---------------+
! #	| # of channels |
! #	+---------------+
! #	| info          |
! #	|               |
! #	+---------------+
! #
! # The magic word consists of the 4 characters '.snd'.  Apart from the
! # info field, all header fields are 4 bytes in size.  They are all
! # 32-bit unsigned integers encoded in big-endian byte order.
! #
! # The header size really gives the start of the data.
! # The data size is the physical size of the data.  From the other
! # parameter the number of frames can be calculated.
! # The encoding gives the way in which audio samples are encoded.
! # Possible values are listed below.
! # The info field currently consists of an ASCII string giving a
! # human-readable description of the audio file.  The info field is
! # padded with NUL bytes to the header size.
! #
! # Usage.
! #
! # Reading audio files:
! #	f = sunau.open(file, 'r')
! # where file is either the name of a file or an open file pointer.
! # The open file pointer must have methods read(), seek(), and close().
! # When the setpos() and rewind() methods are not used, the seek()
! # method is not  necessary.
! #
! # This returns an instance of a class with the following public methods:
! #	getnchannels()	-- returns number of audio channels (1 for
! #			   mono, 2 for stereo)
! #	getsampwidth()	-- returns sample width in bytes
! #	getframerate()	-- returns sampling frequency
! #	getnframes()	-- returns number of audio frames
! #	getcomptype()	-- returns compression type ('NONE' or 'ULAW')
! #	getcompname()	-- returns human-readable version of
! #			   compression type ('not compressed' matches 'NONE')
! #	getparams()	-- returns a tuple consisting of all of the
! #			   above in the above order
! #	getmarkers()	-- returns None (for compatibility with the
! #			   aifc module)
! #	getmark(id)	-- raises an error since the mark does not
! #			   exist (for compatibility with the aifc module)
! #	readframes(n)	-- returns at most n frames of audio
! #	rewind()	-- rewind to the beginning of the audio stream
! #	setpos(pos)	-- seek to the specified position
! #	tell()		-- return the current position
! #	close()		-- close the instance (make it unusable)
! # The position returned by tell() and the position given to setpos()
! # are compatible and have nothing to do with the actual postion in the
! # file.
! # The close() method is called automatically when the class instance
! # is destroyed.
! #
! # Writing audio files:
! #	f = sunau.open(file, 'w')
! # where file is either the name of a file or an open file pointer.
! # The open file pointer must have methods write(), tell(), seek(), and
! # close().
! #
! # This returns an instance of a class with the following public methods:
! #	setnchannels(n)	-- set the number of channels
! #	setsampwidth(n)	-- set the sample width
! #	setframerate(n)	-- set the frame rate
! #	setnframes(n)	-- set the number of frames
! #	setcomptype(type, name)
! #			-- set the compression type and the
! #			   human-readable compression type
! #	setparams(tuple)-- set all parameters at once
! #	tell()		-- return current position in output file
! #	writeframesraw(data)
! #			-- write audio frames without pathing up the
! #			   file header
! #	writeframes(data)
! #			-- write audio frames and patch up the file header
! #	close()		-- patch up the file header and close the
! #			   output file
! # You should set the parameters before the first writeframesraw or
! # writeframes.  The total number of frames does not need to be set,
! # but when it is set to the correct value, the header does not have to
! # be patched up.
! # It is best to first set all parameters, perhaps possibly the
! # compression type, and then write audio frames using writeframesraw.
! # When all frames have been written, either call writeframes('') or
! # close() to patch up the sizes in the header.
! # The close() method is called automatically when the class instance
! # is destroyed.
  
  # from <multimedia/audio_filehdr.h>
--- 1,106 ----
! """Stuff to parse Sun and NeXT audio files.
! 
! An audio consists of a header followed by the data.  The structure
! of the header is as follows.
! 
!         +---------------+
!         | magic word    |
!         +---------------+
!         | header size   |
!         +---------------+
!         | data size     |
!         +---------------+
!         | encoding      |
!         +---------------+
!         | sample rate   |
!         +---------------+
!         | # of channels |
!         +---------------+
!         | info          |
!         |               |
!         +---------------+
! 
! The magic word consists of the 4 characters '.snd'.  Apart from the
! info field, all header fields are 4 bytes in size.  They are all
! 32-bit unsigned integers encoded in big-endian byte order.
! 
! The header size really gives the start of the data.
! The data size is the physical size of the data.  From the other
! parameter the number of frames can be calculated.
! The encoding gives the way in which audio samples are encoded.
! Possible values are listed below.
! The info field currently consists of an ASCII string giving a
! human-readable description of the audio file.  The info field is
! padded with NUL bytes to the header size.
! 
! Usage.
! 
! Reading audio files:
!         f = sunau.open(file, 'r')
! where file is either the name of a file or an open file pointer.
! The open file pointer must have methods read(), seek(), and close().
! When the setpos() and rewind() methods are not used, the seek()
! method is not  necessary.
! 
! This returns an instance of a class with the following public methods:
!         getnchannels()	-- returns number of audio channels (1 for
!         		   mono, 2 for stereo)
!         getsampwidth()	-- returns sample width in bytes
!         getframerate()	-- returns sampling frequency
!         getnframes()	-- returns number of audio frames
!         getcomptype()	-- returns compression type ('NONE' or 'ULAW')
!         getcompname()	-- returns human-readable version of
!         		   compression type ('not compressed' matches 'NONE')
!         getparams()	-- returns a tuple consisting of all of the
!         		   above in the above order
!         getmarkers()	-- returns None (for compatibility with the
!         		   aifc module)
!         getmark(id)	-- raises an error since the mark does not
!         		   exist (for compatibility with the aifc module)
!         readframes(n)	-- returns at most n frames of audio
!         rewind()	-- rewind to the beginning of the audio stream
!         setpos(pos)	-- seek to the specified position
!         tell()		-- return the current position
!         close()		-- close the instance (make it unusable)
! The position returned by tell() and the position given to setpos()
! are compatible and have nothing to do with the actual postion in the
! file.
! The close() method is called automatically when the class instance
! is destroyed.
! 
! Writing audio files:
!         f = sunau.open(file, 'w')
! where file is either the name of a file or an open file pointer.
! The open file pointer must have methods write(), tell(), seek(), and
! close().
! 
! This returns an instance of a class with the following public methods:
!         setnchannels(n)	-- set the number of channels
!         setsampwidth(n)	-- set the sample width
!         setframerate(n)	-- set the frame rate
!         setnframes(n)	-- set the number of frames
!         setcomptype(type, name)
!         		-- set the compression type and the
!         		   human-readable compression type
!         setparams(tuple)-- set all parameters at once
!         tell()		-- return current position in output file
!         writeframesraw(data)
!         		-- write audio frames without pathing up the
!         		   file header
!         writeframes(data)
!         		-- write audio frames and patch up the file header
!         close()		-- patch up the file header and close the
!         		   output file
! You should set the parameters before the first writeframesraw or
! writeframes.  The total number of frames does not need to be set,
! but when it is set to the correct value, the header does not have to
! be patched up.
! It is best to first set all parameters, perhaps possibly the
! compression type, and then write audio frames using writeframesraw.
! When all frames have been written, either call writeframes('') or
! close() to patch up the sizes in the header.
! The close() method is called automatically when the class instance
! is destroyed.
! """
  
  # from <multimedia/audio_filehdr.h>

Index: sunaudio.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/sunaudio.py,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -r1.3 -r1.4
*** sunaudio.py	1992/06/03 16:47:49	1.3
--- sunaudio.py	2000/02/04 15:28:41	1.4
***************
*** 1,3 ****
! # Module 'sunaudio' -- interpret sun audio headers
  
  MAGIC = '.snd'
--- 1,3 ----
! """Interpret sun audio headers."""
  
  MAGIC = '.snd'
***************
*** 6,18 ****
  
  
- # convert a 4-char value to integer
- 
  def get_long_be(s):
  	return (ord(s[0])<<24) | (ord(s[1])<<16) | (ord(s[2])<<8) | ord(s[3])
  
  
- # read a sound header from an open file
- 
  def gethdr(fp):
  	if fp.read(4) <> MAGIC:
  		raise error, 'gethdr: bad magic word'
--- 6,16 ----
  
  
  def get_long_be(s):
+ 	"""Convert a 4-char value to integer."""
  	return (ord(s[0])<<24) | (ord(s[1])<<16) | (ord(s[2])<<8) | ord(s[3])
  
  
  def gethdr(fp):
+ 	"""Read a sound header from an open file."""
  	if fp.read(4) <> MAGIC:
  		raise error, 'gethdr: bad magic word'
***************
*** 32,38 ****
  
  
- # read and print the sound header of a named file
- 
  def printhdr(file):
  	hdr = gethdr(open(file, 'r'))
  	data_size, encoding, sample_rate, channels, info = hdr
--- 30,35 ----
  
  
  def printhdr(file):
+ 	"""Read and print the sound header of a named file."""
  	hdr = gethdr(open(file, 'r'))
  	data_size, encoding, sample_rate, channels, info = hdr

Index: symbol.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/symbol.py,v
retrieving revision 1.8
retrieving revision 1.9
diff -C2 -r1.8 -r1.9
*** symbol.py	1998/03/26 21:13:02	1.8
--- symbol.py	2000/02/04 15:28:41	1.9
***************
*** 1,6 ****
  #! /usr/bin/env python
! #
! #  Non-terminal symbols of Python grammar (from "graminit.h")
! #
  #  This file is automatically generated; please don't muck it up!
  #
--- 1,6 ----
  #! /usr/bin/env python
! 
! """Non-terminal symbols of Python grammar (from "graminit.h")."""
! 
  #  This file is automatically generated; please don't muck it up!
  #

Index: tempfile.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/tempfile.py,v
retrieving revision 1.19
retrieving revision 1.20
diff -C2 -r1.19 -r1.20
*** tempfile.py	1999/06/01 18:55:36	1.19
--- tempfile.py	2000/02/04 15:28:41	1.20
***************
*** 1,4 ****
! # Temporary file name allocation
! #
  # XXX This tries to be not UNIX specific, but I don't know beans about
  # how to choose a temp directory or filename on MS-DOS or other
--- 1,4 ----
! """Temporary files and filenames."""
! 
  # XXX This tries to be not UNIX specific, but I don't know beans about
  # how to choose a temp directory or filename on MS-DOS or other
***************
*** 15,21 ****
  
  
- # Function to calculate the directory to use
- 
  def gettempdir():
      global tempdir
      if tempdir is not None:
--- 15,20 ----
  
  
  def gettempdir():
+     """Function to calculate the directory to use."""
      global tempdir
      if tempdir is not None:
***************
*** 59,67 ****
  
  
- # Function to calculate a prefix of the filename to use
- 
  _pid = None
  
  def gettempprefix():
      global template, _pid
      if os.name == 'posix' and _pid and _pid != os.getpid():
--- 58,65 ----
  
  
  _pid = None
  
  def gettempprefix():
+     """Function to calculate a prefix of the filename to use."""
      global template, _pid
      if os.name == 'posix' and _pid and _pid != os.getpid():
***************
*** 86,92 ****
  
  
- # User-callable function to return a unique temporary file name
- 
  def mktemp(suffix=""):
      global counter
      dir = gettempdir()
--- 84,89 ----
  
  
  def mktemp(suffix=""):
+     """User-callable function to return a unique temporary file name."""
      global counter
      dir = gettempdir()
***************
*** 127,130 ****
--- 124,128 ----
  
  def TemporaryFile(mode='w+b', bufsize=-1, suffix=""):
+     """Create and return a temporary file (opened read-write by default)."""
      name = mktemp(suffix)
      if os.name == 'posix':

Index: threading.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/threading.py,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -r1.5 -r1.6
*** threading.py	1999/09/29 15:26:52	1.5
--- threading.py	2000/02/04 15:28:41	1.6
***************
*** 1,4 ****
! # threading.py:
! # Proposed new threading module, emulating a subset of Java's threading model
  
  import sys
--- 1,3 ----
! """Proposed new threading module, emulating a subset of Java's threading model."""
  
  import sys

Index: toaiff.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/toaiff.py,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -r1.4 -r1.5
*** toaiff.py	1999/02/24 18:49:15	1.4
--- toaiff.py	2000/02/04 15:28:41	1.5
***************
*** 1,9 ****
! # Convert "arbitrary" sound files to AIFF files (Apple and SGI's audio format).
! # Input may be compressed.
! # Uncompressed file type may be AIFF, WAV, VOC, 8SVX, NeXT/Sun, and others.
! # An exception is raised if the file is not of a recognized type.
! # Returned filename is either the input filename or a temporary filename;
! # in the latter case the caller must ensure that it is removed.
! # Other temporary files used are removed by the function.
  
  import os
--- 1,11 ----
! """Convert "arbitrary" sound files to AIFF (Apple and SGI's audio format).
! 
! Input may be compressed.
! Uncompressed file type may be AIFF, WAV, VOC, 8SVX, NeXT/Sun, and others.
! An exception is raised if the file is not of a recognized type.
! Returned filename is either the input filename or a temporary filename;
! in the latter case the caller must ensure that it is removed.
! Other temporary files used are removed by the function.
! """
  
  import os

Index: token.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/token.py,v
retrieving revision 1.6
retrieving revision 1.7
diff -C2 -r1.6 -r1.7
*** token.py	1998/03/26 21:13:08	1.6
--- token.py	2000/02/04 15:28:41	1.7
***************
*** 1,6 ****
  #! /usr/bin/env python
! #
! #  Tokens (from "token.h")
! #
  #  This file is automatically generated; please don't muck it up!
  #
--- 1,6 ----
  #! /usr/bin/env python
! 
! """Token constants (from "token.h")."""
! 
  #  This file is automatically generated; please don't muck it up!
  #

Index: traceback.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/traceback.py,v
retrieving revision 1.13
retrieving revision 1.14
diff -C2 -r1.13 -r1.14
*** traceback.py	1998/03/18 17:48:06	1.13
--- traceback.py	2000/02/04 15:28:41	1.14
***************
*** 1,3 ****
! # Format and print Python stack traces
  
  import linecache
--- 1,3 ----
! """Extract, format and print information about Python stack traces."""
  
  import linecache
***************
*** 11,14 ****
--- 11,16 ----
  
  def print_list(extracted_list, file=None):
+ 	"""Print the list of tuples as returned by extract_tb() or
+ 	extract_stack() as a formatted stack trace to the given file."""
  	if not file:
  		file = sys.stderr
***************
*** 20,23 ****
--- 22,31 ----
  
  def format_list(extracted_list):
+ 	"""Given a list of tuples as returned by extract_tb() or
+ 	extract_stack(), return a list of strings ready for printing.
+ 	Each string in the resulting list corresponds to the item with
+ 	the same index in the argument list.  Each string ends in a
+ 	newline; the strings may contain internal newlines as well, for
+ 	those items whose source text line is not None."""
  	list = []
  	for filename, lineno, name, line in extracted_list:
***************
*** 30,33 ****
--- 38,45 ----
  
  def print_tb(tb, limit=None, file=None):
+ 	"""Print up to 'limit' stack trace entries from the traceback 'tb'.
+ 	If 'limit' is omitted or None, all entries are printed.  If 'file' is
+ 	omitted or None, the output goes to sys.stderr; otherwise 'file'
+ 	should be an open file or file-like object with a write() method."""
  	if not file:
  		file = sys.stderr
***************
*** 50,56 ****
--- 62,77 ----
  
  def format_tb(tb, limit = None):
+ 	"""A shorthand for 'format_list(extract_stack(f, limit))."""
  	return format_list(extract_tb(tb, limit))
  
  def extract_tb(tb, limit = None):
+ 	"""Return a list of up to 'limit' pre-processed stack trace entries
+ 	extracted from the traceback object 'traceback'.  This is useful for
+ 	alternate formatting of stack traces.  If 'limit' is omitted or None,
+ 	all entries are extracted.  A pre-processed stack trace entry is a
+ 	quadruple (filename, line number, function name, text) representing
+ 	the information that is usually printed for a stack trace.  The text
+ 	is a string with leading and trailing whitespace stripped; if the
+ 	source is not available it is None."""
  	if limit is None:
  		if hasattr(sys, 'tracebacklimit'):
***************
*** 74,77 ****
--- 95,106 ----
  
  def print_exception(etype, value, tb, limit=None, file=None):
+ 	"""Print exception information and up to 'limit' stack trace entries
+ 	from the traceback 'tb' to 'file'.  This differs from print_tb() in
+ 	the following ways: (1) if traceback is not None, it prints a header
+ 	"Traceback (innermost last):"; (2) it prints the exception type and
+ 	value after the stack trace; (3) if type is SyntaxError and value has
+ 	the appropriate format, it prints the line where the syntax error
+ 	occurred with a caret on the next line indicating the approximate
+ 	position of the error."""
  	if not file:
  		file = sys.stderr
***************
*** 85,88 ****
--- 114,123 ----
  
  def format_exception(etype, value, tb, limit = None):
+ 	"""Format a stack trace and the exception information.  The arguments
+ 	have the same meaning as the corresponding arguments to
+ 	print_exception().  The return value is a list of strings, each
+ 	ending in a newline and some containing internal newlines.  When 
+ 	these lines are contatenated and printed, exactly the same text is
+ 	printed as does print_exception()."""
  	if tb:
  		list = ['Traceback (innermost last):\n']
***************
*** 94,97 ****
--- 129,140 ----
  
  def format_exception_only(etype, value):
+ 	"""Format the exception part of a traceback.  The arguments are the
+ 	exception type and value such as given by sys.last_type and
+ 	sys.last_value. The return value is a list of strings, each ending
+ 	in a newline.  Normally, the list contains a single string;
+ 	however, for SyntaxError exceptions, it contains several lines that
+ 	(when printed) display detailed information about where the syntax
+ 	error occurred.  The message indicating which exception occurred is
+ 	the always last string in the list."""
  	list = []
  	if type(etype) == types.ClassType:
***************
*** 129,132 ****
--- 172,179 ----
  
  def print_exc(limit=None, file=None):
+ 	"""This is a shorthand for 'print_exception(sys.exc_type,
+ 	sys.exc_value, sys.exc_traceback, limit, file)'.
+ 	(In fact, it uses sys.exc_info() to retrieve the same information
+ 	in a thread-safe way.)"""
  	if not file:
  		file = sys.stderr
***************
*** 138,141 ****
--- 185,190 ----
  
  def print_last(limit=None, file=None):
+ 	"""This is a shorthand for 'print_exception(sys.last_type,
+ 	sys.last_value, sys.last_traceback, limit, file)'."""
  	if not file:
  		file = sys.stderr
***************
*** 145,148 ****
--- 194,201 ----
  
  def print_stack(f=None, limit=None, file=None):
+ 	"""This function prints a stack trace from its invocation point.
+ 	The optional 'f' argument can be used to specify an alternate stack
+ 	frame at which to start. The optional 'limit' and 'file' arguments
+ 	have the same meaning as for print_exception()."""
  	if f is None:
  		try:
***************
*** 153,156 ****
--- 206,210 ----
  
  def format_stack(f=None, limit=None):
+ 	"""A shorthand for 'format_list(extract_stack(f, limit))'."""
  	if f is None:
  		try:
***************
*** 161,164 ****
--- 215,224 ----
  
  def extract_stack(f=None, limit = None):
+ 	"""Extract the raw traceback from the current stack frame.  The
+ 	return value has the same format as for extract_tb().  The optional
+ 	'f' and 'limit' arguments have the same meaning as for print_stack(). 
+ 	Each item in the list is a quadruple (filename, line number,
+ 	function name, text), and the entries are in order from outermost
+ 	to innermost stack frame."""
  	if f is None:
  		try:
***************
*** 185,195 ****
  	return list
  
- # Calculate the correct line number of the traceback given in tb (even
- # with -O on).
- # Coded by Marc-Andre Lemburg from the example of PyCode_Addr2Line()
- # in compile.c.
- # Revised version by Jim Hugunin to work with JPython too.
- 
  def tb_lineno(tb):
  	c = tb.tb_frame.f_code
  	if not hasattr(c, 'co_lnotab'):
--- 245,256 ----
  	return list
  
  def tb_lineno(tb):
+ 	"""Calculate the correct line number of the traceback given in tb
+ 	(even with -O on)."""
+ 
+ 	# Coded by Marc-Andre Lemburg from the example of PyCode_Addr2Line()
+ 	# in compile.c.
+ 	# Revised version by Jim Hugunin to work with JPython too.
+ 
  	c = tb.tb_frame.f_code
  	if not hasattr(c, 'co_lnotab'):

Index: tty.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/tty.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -r1.1 -r1.2
*** tty.py	1994/09/12 10:36:34	1.1
--- tty.py	2000/02/04 15:28:41	1.2
***************
*** 1,3 ****
! # tty.py -- Terminal utilities.
  # Author: Steen Lumholt.
  
--- 1,4 ----
! """Terminal utilities."""
! 
  # Author: Steen Lumholt.
  
***************
*** 14,19 ****
  CC = 6
  
- # Put terminal into a raw mode.
  def setraw(fd, when=TCSAFLUSH):
  	mode = tcgetattr(fd)
  	mode[IFLAG] = mode[IFLAG] & ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON)
--- 15,20 ----
  CC = 6
  
  def setraw(fd, when=TCSAFLUSH):
+ 	"""Put terminal into a raw mode."""
  	mode = tcgetattr(fd)
  	mode[IFLAG] = mode[IFLAG] & ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON)
***************
*** 26,31 ****
  	tcsetattr(fd, when, mode)
  
- # Put terminal into a cbreak mode.
  def setcbreak(fd, when=TCSAFLUSH):
  	mode = tcgetattr(fd)
  	mode[LFLAG] = mode[LFLAG] & ~(ECHO | ICANON)
--- 27,32 ----
  	tcsetattr(fd, when, mode)
  
  def setcbreak(fd, when=TCSAFLUSH):
+ 	"""Put terminal into a cbreak mode."""
  	mode = tcgetattr(fd)
  	mode[LFLAG] = mode[LFLAG] & ~(ECHO | ICANON)

Index: types.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/types.py,v
retrieving revision 1.12
retrieving revision 1.13
diff -C2 -r1.12 -r1.13
*** types.py	1999/03/19 19:08:03	1.12
--- types.py	2000/02/04 15:28:41	1.13
***************
*** 1,4 ****
! # Define names for all type symbols known in the standard interpreter.
! # Types that are part of optional modules (e.g. array) are not listed.
  
  import sys
--- 1,6 ----
! """Define names for all type symbols known in the standard interpreter.
! 
! Types that are part of optional modules (e.g. array) are not listed.
! """
  
  import sys

Index: tzparse.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/tzparse.py,v
retrieving revision 1.6
retrieving revision 1.7
diff -C2 -r1.6 -r1.7
*** tzparse.py	1997/10/22 20:58:20	1.6
--- tzparse.py	2000/02/04 15:28:41	1.7
***************
*** 1,3 ****
! # Parse a timezone specification.
  # XXX Unfinished.
  # XXX Only the typical form "XXXhhYYY;ddd/hh,ddd/hh" is currently supported.
--- 1,4 ----
! """Parse a timezone specification."""
! 
  # XXX Unfinished.
  # XXX Only the typical form "XXXhhYYY;ddd/hh,ddd/hh" is currently supported.
***************
*** 9,12 ****
--- 10,19 ----
  
  def tzparse(tzstr):
+ 	"""Given a timezone spec, return a tuple of information
+ 	(tzname, delta, dstname, daystart, hourstart, dayend, hourend),
+ 	where 'tzname' is the name of the timezone, 'delta' is the offset
+ 	in hours from GMT, 'dstname' is the name of the daylight-saving
+ 	timezone, and 'daystart'/'hourstart' and 'dayend'/'hourend'
+ 	specify the starting and ending points for daylight saving time."""
  	global tzprog
  	if tzprog == None:
***************
*** 25,28 ****
--- 32,38 ----
  
  def tzlocaltime(secs, params):
+ 	"""Given a Unix time in seconds and a tuple of information about
+ 	a timezone as returned by tzparse(), return the local time in the
+ 	form (year, month, day, hour, min, sec, yday, wday, tzname)."""
  	import time
  	(tzname, delta, dstname, daystart, hourstart, dayend, hourend) = params
***************
*** 35,38 ****
--- 45,49 ----
  
  def tzset():
+ 	"""Determine the current timezone from the "TZ" environment variable."""
  	global tzparams, timezone, altzone, daylight, tzname
  	import os
***************
*** 45,48 ****
--- 56,61 ----
  
  def isdst(secs):
+ 	"""Return true if daylight-saving time is in effect for the given
+ 	Unix time in the current timezone."""
  	import time
  	(tzname, delta, dstname, daystart, hourstart, dayend, hourend) = \
***************
*** 55,58 ****
--- 68,72 ----
  
  def localtime(secs):
+ 	"""Get the local time in the current timezone."""
  	return tzlocaltime(secs, tzparams)
  

Index: urllib.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/urllib.py,v
retrieving revision 1.90
retrieving revision 1.91
diff -C2 -r1.90 -r1.91
*** urllib.py	2000/02/01 23:36:55	1.90
--- urllib.py	2000/02/04 15:28:41	1.91
***************
*** 1,25 ****
! # Open an arbitrary URL
! #
! # See the following document for more info on URLs:
! # "Names and Addresses, URIs, URLs, URNs, URCs", at
! # http://www.w3.org/pub/WWW/Addressing/Overview.html
! #
! # See also the HTTP spec (from which the error codes are derived):
! # "HTTP - Hypertext Transfer Protocol", at
! # http://www.w3.org/pub/WWW/Protocols/
! #
! # Related standards and specs:
! # - RFC1808: the "relative URL" spec. (authoritative status)
! # - RFC1738 - the "URL standard". (authoritative status)
! # - RFC1630 - the "URI spec". (informational status)
! #
! # The object returned by URLopener().open(file) will differ per
! # protocol.  All you know is that is has methods read(), readline(),
! # readlines(), fileno(), close() and info().  The read*(), fileno()
! # and close() methods work like those of open files. 
! # The info() method returns a mimetools.Message object which can be
! # used to query various info about the object, if available.
! # (mimetools.Message objects are queried with the getheader() method.)
  
  import string
  import socket
--- 1,26 ----
! """Open an arbitrary URL.
  
+ See the following document for more info on URLs:
+ "Names and Addresses, URIs, URLs, URNs, URCs", at
+ http://www.w3.org/pub/WWW/Addressing/Overview.html
+ 
+ See also the HTTP spec (from which the error codes are derived):
+ "HTTP - Hypertext Transfer Protocol", at
+ http://www.w3.org/pub/WWW/Protocols/
+ 
+ Related standards and specs:
+ - RFC1808: the "relative URL" spec. (authoritative status)
+ - RFC1738 - the "URL standard". (authoritative status)
+ - RFC1630 - the "URI spec". (informational status)
+ 
+ The object returned by URLopener().open(file) will differ per
+ protocol.  All you know is that is has methods read(), readline(),
+ readlines(), fileno(), close() and info().  The read*(), fileno()
+ and close() methods work like those of open files. 
+ The info() method returns a mimetools.Message object which can be
+ used to query various info about the object, if available.
+ (mimetools.Message objects are queried with the getheader() method.)
+ """
+ 
  import string
  import socket
***************
*** 70,81 ****
  
  
- # Class to open URLs.
- # This is a class rather than just a subroutine because we may need
- # more than one set of global protocol-specific options.
- # Note -- this is a base class for those who don't want the
- # automatic handling of errors type 302 (relocated) and 401
- # (authorization needed).
  ftpcache = {}
  class URLopener:
  
      __tempfiles = None
--- 71,82 ----
  
  
  ftpcache = {}
  class URLopener:
+     """Class to open URLs.
+     This is a class rather than just a subroutine because we may need
+     more than one set of global protocol-specific options.
+     Note -- this is a base class for those who don't want the
+     automatic handling of errors type 302 (relocated) and 401
+     (authorization needed)."""
  
      __tempfiles = None
***************
*** 126,137 ****
              self.tempcache.clear()
  
-     # Add a header to be used by the HTTP interface only
-     # e.g. u.addheader('Accept', 'sound/basic')
      def addheader(self, *args):
          self.addheaders.append(args)
  
      # External interface
-     # Use URLopener().open(file) instead of open(file, 'r')
      def open(self, fullurl, data=None):
          fullurl = unwrap(fullurl)
          if self.tempcache and self.tempcache.has_key(fullurl):
--- 127,138 ----
              self.tempcache.clear()
  
      def addheader(self, *args):
+         """Add a header to be used by the HTTP interface only
+         e.g. u.addheader('Accept', 'sound/basic')"""
          self.addheaders.append(args)
  
      # External interface
      def open(self, fullurl, data=None):
+         """Use URLopener().open(file) instead of open(file, 'r')."""
          fullurl = unwrap(fullurl)
          if self.tempcache and self.tempcache.has_key(fullurl):
***************
*** 164,176 ****
              raise IOError, ('socket error', msg), sys.exc_info()[2]
  
-     # Overridable interface to open unknown URL type
      def open_unknown(self, fullurl, data=None):
          type, url = splittype(fullurl)
          raise IOError, ('url error', 'unknown url type', type)
  
      # External interface
-     # retrieve(url) returns (filename, None) for a local object
-     # or (tempfilename, headers) for a remote object
      def retrieve(self, url, filename=None, reporthook=None):
          url = unwrap(url)
          if self.tempcache and self.tempcache.has_key(url):
--- 165,177 ----
              raise IOError, ('socket error', msg), sys.exc_info()[2]
  
      def open_unknown(self, fullurl, data=None):
+         """Overridable interface to open unknown URL type."""
          type, url = splittype(fullurl)
          raise IOError, ('url error', 'unknown url type', type)
  
      # External interface
      def retrieve(self, url, filename=None, reporthook=None):
+         """retrieve(url) returns (filename, None) for a local object
+         or (tempfilename, headers) for a remote object."""
          url = unwrap(url)
          if self.tempcache and self.tempcache.has_key(url):
***************
*** 224,229 ****
      # Each method named open_<type> knows how to open that type of URL
  
-     # Use HTTP protocol
      def open_http(self, url, data=None):
          import httplib
          user_passwd = None
--- 225,230 ----
      # Each method named open_<type> knows how to open that type of URL
  
      def open_http(self, url, data=None):
+         """Use HTTP protocol."""
          import httplib
          user_passwd = None
***************
*** 277,284 ****
                  return self.http_error(url, fp, errcode, errmsg, headers, data)
  
-     # Handle http errors.
-     # Derived class can override this, or provide specific handlers
-     # named http_error_DDD where DDD is the 3-digit error code
      def http_error(self, url, fp, errcode, errmsg, headers, data=None):
          # First check if there's a specific handler for this error
          name = 'http_error_%d' % errcode
--- 278,285 ----
                  return self.http_error(url, fp, errcode, errmsg, headers, data)
  
      def http_error(self, url, fp, errcode, errmsg, headers, data=None):
+         """Handle http errors.
+         Derived class can override this, or provide specific handlers
+         named http_error_DDD where DDD is the 3-digit error code."""
          # First check if there's a specific handler for this error
          name = 'http_error_%d' % errcode
***************
*** 292,304 ****
          return self.http_error_default(url, fp, errcode, errmsg, headers)
  
-     # Default http error handler: close the connection and raises IOError
      def http_error_default(self, url, fp, errcode, errmsg, headers):
          void = fp.read()
          fp.close()
          raise IOError, ('http error', errcode, errmsg, headers)
  
-     # Use HTTPS protocol
      if hasattr(socket, "ssl"):
          def open_https(self, url):
              import httplib
              if type(url) is type(""):
--- 293,305 ----
          return self.http_error_default(url, fp, errcode, errmsg, headers)
  
      def http_error_default(self, url, fp, errcode, errmsg, headers):
+         """Default error handler: close the connection and raise IOError."""
          void = fp.read()
          fp.close()
          raise IOError, ('http error', errcode, errmsg, headers)
  
      if hasattr(socket, "ssl"):
          def open_https(self, url):
+             """Use HTTPS protocol."""
              import httplib
              if type(url) is type(""):
***************
*** 334,339 ****
                  return self.http_error(url, fp, errcode, errmsg, headers)
    
-     # Use Gopher protocol
      def open_gopher(self, url):
          import gopherlib
          host, selector = splithost(url)
--- 335,340 ----
                  return self.http_error(url, fp, errcode, errmsg, headers)
    
      def open_gopher(self, url):
+         """Use Gopher protocol."""
          import gopherlib
          host, selector = splithost(url)
***************
*** 350,355 ****
          return addinfourl(fp, noheaders(), "gopher:" + url)
  
-     # Use local file or FTP depending on form of URL
      def open_file(self, url):
          if url[:2] == '//' and url[2:3] != '/':
              return self.open_ftp(url)
--- 351,356 ----
          return addinfourl(fp, noheaders(), "gopher:" + url)
  
      def open_file(self, url):
+         """Use local file or FTP depending on form of URL."""
          if url[:2] == '//' and url[2:3] != '/':
              return self.open_ftp(url)
***************
*** 357,362 ****
              return self.open_local_file(url)
  
-     # Use local file
      def open_local_file(self, url):
          import mimetypes, mimetools, StringIO
          mtype = mimetypes.guess_type(url)[0]
--- 358,363 ----
              return self.open_local_file(url)
  
      def open_local_file(self, url):
+         """Use local file."""
          import mimetypes, mimetools, StringIO
          mtype = mimetypes.guess_type(url)[0]
***************
*** 380,385 ****
          raise IOError, ('local file error', 'not on local host')
  
-     # Use FTP protocol
      def open_ftp(self, url):
          host, path = splithost(url)
          if not host: raise IOError, ('ftp error', 'no host given')
--- 381,386 ----
          raise IOError, ('local file error', 'not on local host')
  
      def open_ftp(self, url):
+         """Use FTP protocol."""
          host, path = splithost(url)
          if not host: raise IOError, ('ftp error', 'no host given')
***************
*** 434,439 ****
              raise IOError, ('ftp error', msg), sys.exc_info()[2]
  
-     # Use "data" URL
      def open_data(self, url, data=None):
          # ignore POSTed data
          #
--- 435,440 ----
              raise IOError, ('ftp error', msg), sys.exc_info()[2]
  
      def open_data(self, url, data=None):
+         """Use "data" URL."""
          # ignore POSTed data
          #
***************
*** 475,480 ****
  
  
- # Derived class with handlers for errors we can handle (perhaps)
  class FancyURLopener(URLopener):
  
      def __init__(self, *args):
--- 476,481 ----
  
  
  class FancyURLopener(URLopener):
+     """Derived class with handlers for errors we can handle (perhaps)."""
  
      def __init__(self, *args):
***************
*** 482,492 ****
          self.auth_cache = {}
  
-     # Default error handling -- don't raise an exception
      def http_error_default(self, url, fp, errcode, errmsg, headers):
          return addinfourl(fp, headers, "http:" + url)
  
!     # Error 302 -- relocated (temporarily)
!     def http_error_302(self, url, fp, errcode, errmsg, headers,
!                data=None): 
          # XXX The server can force infinite recursion here!
          if headers.has_key('location'):
--- 483,492 ----
          self.auth_cache = {}
  
      def http_error_default(self, url, fp, errcode, errmsg, headers):
+         """Default error handling -- don't raise an exception."""
          return addinfourl(fp, headers, "http:" + url)
  
!     def http_error_302(self, url, fp, errcode, errmsg, headers, data=None): 
!         """Error 302 -- relocated (temporarily)."""
          # XXX The server can force infinite recursion here!
          if headers.has_key('location'):
***************
*** 504,516 ****
          else:
              return self.open(newurl, data)
- 
-     # Error 301 -- also relocated (permanently)
-     http_error_301 = http_error_302
  
!     # Error 401 -- authentication required
!     # See this URL for a description of the basic authentication scheme:
!     # http://www.ics.uci.edu/pub/ietf/http/draft-ietf-http-v10-spec-00.txt
!     def http_error_401(self, url, fp, errcode, errmsg, headers,
!                data=None): 
          if headers.has_key('www-authenticate'):
              stuff = headers['www-authenticate']
--- 504,516 ----
          else:
              return self.open(newurl, data)
  
!     def http_error_301(self, url, fp, errcode, errmsg, headers, data=None): 
!         """Error 301 -- also relocated (permanently)."""
!         return self.http_error_302(url, fp, errcode, errmsg, headers, data)
! 
!     def http_error_401(self, url, fp, errcode, errmsg, headers, data=None): 
!         """Error 401 -- authentication required.
!         See this URL for a description of the basic authentication scheme:
!         http://www.ics.uci.edu/pub/ietf/http/draft-ietf-http-v10-spec-00.txt"""
          if headers.has_key('www-authenticate'):
              stuff = headers['www-authenticate']
***************
*** 561,565 ****
  
      def prompt_user_passwd(self, host, realm):
!         # Override this in a GUI environment!
          import getpass
          try:
--- 561,565 ----
  
      def prompt_user_passwd(self, host, realm):
!         """Override this in a GUI environment!"""
          import getpass
          try:
***************
*** 576,582 ****
  # Utility functions
  
- # Return the IP address of the magic hostname 'localhost'
  _localhost = None
  def localhost():
      global _localhost
      if not _localhost:
--- 576,582 ----
  # Utility functions
  
  _localhost = None
  def localhost():
+     """Return the IP address of the magic hostname 'localhost'."""
      global _localhost
      if not _localhost:
***************
*** 584,590 ****
      return _localhost
  
- # Return the IP address of the current host
  _thishost = None
  def thishost():
      global _thishost
      if not _thishost:
--- 584,590 ----
      return _localhost
  
  _thishost = None
  def thishost():
+     """Return the IP address of the current host."""
      global _thishost
      if not _thishost:
***************
*** 592,598 ****
      return _thishost
  
- # Return the set of errors raised by the FTP class
  _ftperrors = None
  def ftperrors():
      global _ftperrors
      if not _ftperrors:
--- 592,598 ----
      return _thishost
  
  _ftperrors = None
  def ftperrors():
+     """Return the set of errors raised by the FTP class."""
      global _ftperrors
      if not _ftperrors:
***************
*** 601,607 ****
      return _ftperrors
  
- # Return an empty mimetools.Message object
  _noheaders = None
  def noheaders():
      global _noheaders
      if not _noheaders:
--- 601,607 ----
      return _ftperrors
  
  _noheaders = None
  def noheaders():
+     """Return an empty mimetools.Message object."""
      global _noheaders
      if not _noheaders:
***************
*** 615,620 ****
  # Utility classes
  
- # Class used by open_ftp() for cache of open FTP connections
  class ftpwrapper:
      def __init__(self, user, passwd, host, port, dirs):
          self.user = user
--- 615,621 ----
  # Utility classes
  
  class ftpwrapper:
+     """Class used by open_ftp() for cache of open FTP connections."""
+ 
      def __init__(self, user, passwd, host, port, dirs):
          self.user = user
***************
*** 624,627 ****
--- 625,629 ----
          self.dirs = dirs
          self.init()
+ 
      def init(self):
          import ftplib
***************
*** 632,635 ****
--- 634,638 ----
          for dir in self.dirs:
              self.ftp.cwd(dir)
+ 
      def retrfile(self, file, type):
          import ftplib
***************
*** 677,680 ****
--- 680,684 ----
          except ftperrors():
              pass
+ 
      def close(self):
          self.endtransfer()
***************
*** 684,689 ****
              pass
  
- # Base class for addinfo and addclosehook
  class addbase:
      def __init__(self, fp):
          self.fp = fp
--- 688,694 ----
              pass
  
  class addbase:
+     """Base class for addinfo and addclosehook."""
+ 
      def __init__(self, fp):
          self.fp = fp
***************
*** 692,698 ****
--- 697,705 ----
          if hasattr(self.fp, "readlines"): self.readlines = self.fp.readlines
          if hasattr(self.fp, "fileno"): self.fileno = self.fp.fileno
+ 
      def __repr__(self):
          return '<%s at %s whose fp = %s>' % (self.__class__.__name__,
                                               `id(self)`, `self.fp`) 
+ 
      def close(self):
          self.read = None
***************
*** 703,712 ****
          self.fp = None
  
- # Class to add a close hook to an open file
  class addclosehook(addbase):
      def __init__(self, fp, closehook, *hookargs):
          addbase.__init__(self, fp)
          self.closehook = closehook
          self.hookargs = hookargs
      def close(self):
          if self.closehook:
--- 710,721 ----
          self.fp = None
  
  class addclosehook(addbase):
+     """Class to add a close hook to an open file."""
+ 
      def __init__(self, fp, closehook, *hookargs):
          addbase.__init__(self, fp)
          self.closehook = closehook
          self.hookargs = hookargs
+ 
      def close(self):
          if self.closehook:
***************
*** 716,742 ****
          addbase.close(self)
  
- # class to add an info() method to an open file
  class addinfo(addbase):
      def __init__(self, fp, headers):
          addbase.__init__(self, fp)
          self.headers = headers
      def info(self):
          return self.headers
  
- # class to add info() and geturl() methods to an open file
  class addinfourl(addbase):
      def __init__(self, fp, headers, url):
          addbase.__init__(self, fp)
          self.headers = headers
          self.url = url
      def info(self):
          return self.headers
      def geturl(self):
          return self.url
  
  
- # Utility to combine a URL with a base URL to form a new URL
- 
  def basejoin(base, url):
      type, path = splittype(url)
      if type:
--- 725,755 ----
          addbase.close(self)
  
  class addinfo(addbase):
+     """class to add an info() method to an open file."""
+ 
      def __init__(self, fp, headers):
          addbase.__init__(self, fp)
          self.headers = headers
+ 
      def info(self):
          return self.headers
  
  class addinfourl(addbase):
+     """class to add info() and geturl() methods to an open file."""
+ 
      def __init__(self, fp, headers, url):
          addbase.__init__(self, fp)
          self.headers = headers
          self.url = url
+ 
      def info(self):
          return self.headers
+ 
      def geturl(self):
          return self.url
  
  
  def basejoin(base, url):
+     """Utility to combine a URL with a base URL to form a new URL."""
      type, path = splittype(url)
      if type:
***************
*** 810,813 ****
--- 823,827 ----
  
  def unwrap(url):
+     """unwrap('<URL:type://host/path>') --> 'type://host/path'."""
      url = string.strip(url)
      if url[:1] == '<' and url[-1:] == '>':
***************
*** 818,821 ****
--- 832,836 ----
  _typeprog = None
  def splittype(url):
+     """splittype('type:opaquestring') --> 'type', 'opaquestring'."""
      global _typeprog
      if _typeprog is None:
***************
*** 831,834 ****
--- 846,850 ----
  _hostprog = None
  def splithost(url):
+     """splithost('//host[:port]/path') --> 'host[:port]', '/path'."""
      global _hostprog
      if _hostprog is None:
***************
*** 842,845 ****
--- 858,862 ----
  _userprog = None
  def splituser(host):
+     """splituser('user[:passwd]@host[:port]') --> 'user[:passwd]', 'host[:port]'."""
      global _userprog
      if _userprog is None:
***************
*** 853,856 ****
--- 870,874 ----
  _passwdprog = None
  def splitpasswd(user):
+     """splitpasswd('user:passwd') -> 'user', 'passwd'."""
      global _passwdprog
      if _passwdprog is None:
***************
*** 862,867 ****
--- 880,887 ----
      return user, None
  
+ # splittag('/path#tag') --> '/path', 'tag'
  _portprog = None
  def splitport(host):
+     """splitport('host:port') --> 'host', 'port'."""
      global _portprog
      if _portprog is None:
***************
*** 873,882 ****
      return host, None
  
- # Split host and port, returning numeric port.
- # Return given default port if no ':' found; defaults to -1.
- # Return numerical port if a valid number are found after ':'.
- # Return None if ':' but not a valid number.
  _nportprog = None
  def splitnport(host, defport=-1):
      global _nportprog
      if _nportprog is None:
--- 893,902 ----
      return host, None
  
  _nportprog = None
  def splitnport(host, defport=-1):
+     """Split host and port, returning numeric port.
+     Return given default port if no ':' found; defaults to -1.
+     Return numerical port if a valid number are found after ':'.
+     Return None if ':' but not a valid number."""
      global _nportprog
      if _nportprog is None:
***************
*** 897,900 ****
--- 917,921 ----
  _queryprog = None
  def splitquery(url):
+     """splitquery('/path?query') --> '/path', 'query'."""
      global _queryprog
      if _queryprog is None:
***************
*** 908,911 ****
--- 929,933 ----
  _tagprog = None
  def splittag(url):
+     """splittag('/path#tag') --> '/path', 'tag'."""
      global _tagprog
      if _tagprog is None:
***************
*** 918,921 ****
--- 940,945 ----
  
  def splitattr(url):
+     """splitattr('/path;attr1=value1;attr2=value2;...') ->
+         '/path', ['attr1=value1', 'attr2=value2', ...]."""
      words = string.splitfields(url, ';')
      return words[0], words[1:]
***************
*** 923,926 ****
--- 947,951 ----
  _valueprog = None
  def splitvalue(attr):
+     """splitvalue('attr=value') --> 'attr', 'value'."""
      global _valueprog
      if _valueprog is None:
***************
*** 933,936 ****
--- 958,962 ----
  
  def splitgophertype(selector):
+     """splitgophertype('/Xselector') --> 'X', 'selector'."""
      if selector[:1] == '/' and selector[1:2]:
          return selector[1], selector[2:]
***************
*** 938,941 ****
--- 964,968 ----
  
  def unquote(s):
+     """unquote('abc%20def') -> 'abc def'."""
      mychr = chr
      myatoi = string.atoi
***************
*** 963,966 ****
--- 990,994 ----
  always_safe = string.letters + string.digits + '_,.-'
  def quote(s, safe = '/'):
+     """quote('abc def') -> 'abc%20def')."""
      # XXX Can speed this up an order of magnitude
      safe = always_safe + safe
***************
*** 984,993 ****
  
  def urlencode(dict):
!      l = []
!      for k, v in dict.items():
!          k = quote_plus(str(k))
!          v = quote_plus(str(v))
!          l.append(k + '=' + v)
!      return string.join(l, '&')
  
  
--- 1012,1022 ----
  
  def urlencode(dict):
!     """Encode a dictionary of form entries into a URL query string."""
!     l = []
!     for k, v in dict.items():
!         k = quote_plus(str(k))
!         v = quote_plus(str(v))
!         l.append(k + '=' + v)
!     return string.join(l, '&')
  
  

Index: urllib2.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/urllib2.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -r1.1 -r1.2
*** urllib2.py	2000/01/20 18:19:08	1.1
--- urllib2.py	2000/02/04 15:28:42	1.2
***************
*** 1,3 ****
! """An extensible library for opening URLs using a variety protocols
  
  The simplest way to use this module is to call the urlopen function,
--- 1,3 ----
! """An extensible library for opening URLs using a variety of protocols
  
  The simplest way to use this module is to call the urlopen function,

Index: urlparse.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/urlparse.py,v
retrieving revision 1.21
retrieving revision 1.22
diff -C2 -r1.21 -r1.22
*** urlparse.py	1999/05/03 18:16:23	1.21
--- urlparse.py	2000/02/04 15:28:42	1.22
***************
*** 1,5 ****
! # Parse (absolute and relative) URLs.  See RFC 1808: "Relative Uniform
! # Resource Locators", by R. Fielding, UC Irvine, June 1995.
  
  # Standard/builtin Python modules
  import string
--- 1,8 ----
! """Parse (absolute and relative) URLs.
  
+ See RFC 1808: "Relative Uniform Resource Locators", by R. Fielding,
+ UC Irvine, June 1995.
+ """
+ 
  # Standard/builtin Python modules
  import string
***************
*** 40,49 ****
  
  
- # Parse a URL into 6 components:
- # <scheme>://<netloc>/<path>;<params>?<query>#<fragment>
- # Return a 6-tuple: (scheme, netloc, path, params, query, fragment).
- # Note that we don't break the components up in smaller bits
- # (e.g. netloc is a single string) and we don't expand % escapes.
  def urlparse(url, scheme = '', allow_fragments = 1):
  	key = url, scheme, allow_fragments
  	cached = _parse_cache.get(key, None)
--- 43,52 ----
  
  
  def urlparse(url, scheme = '', allow_fragments = 1):
+ 	"""Parse a URL into 6 components:
+ 	<scheme>://<netloc>/<path>;<params>?<query>#<fragment>
+ 	Return a 6-tuple: (scheme, netloc, path, params, query, fragment).
+ 	Note that we don't break the components up in smaller bits
+ 	(e.g. netloc is a single string) and we don't expand % escapes."""
  	key = url, scheme, allow_fragments
  	cached = _parse_cache.get(key, None)
***************
*** 108,116 ****
  	return tuple
  
- # Put a parsed URL back together again.  This may result in a slightly
- # different, but equivalent URL, if the URL that was parsed originally
- # had redundant delimiters, e.g. a ? with an empty query (the draft
- # states that these are equivalent).
  def urlunparse((scheme, netloc, url, params, query, fragment)):
  	if netloc or (scheme in uses_netloc and url[:2] == '//'):
  		if url[:1] != '/': url = '/' + url
--- 111,119 ----
  	return tuple
  
  def urlunparse((scheme, netloc, url, params, query, fragment)):
+ 	"""Put a parsed URL back together again.  This may result in a
+ 	slightly different, but equivalent URL, if the URL that was parsed
+ 	originally had redundant delimiters, e.g. a ? with an empty query
+ 	(the draft states that these are equivalent)."""
  	if netloc or (scheme in uses_netloc and url[:2] == '//'):
  		if url[:1] != '/': url = '/' + url
***************
*** 126,132 ****
  	return url
  
- # Join a base URL and a possibly relative URL to form an absolute
- # interpretation of the latter.
  def urljoin(base, url, allow_fragments = 1):
  	if not base:
  		return url
--- 129,135 ----
  	return url
  
  def urljoin(base, url, allow_fragments = 1):
+ 	"""Join a base URL and a possibly relative URL to form an absolute
+ 	interpretation of the latter."""
  	if not base:
  		return url

Index: uu.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/uu.py,v
retrieving revision 1.10
retrieving revision 1.11
diff -C2 -r1.10 -r1.11
*** uu.py	1999/01/05 18:02:24	1.10
--- uu.py	2000/02/04 15:28:42	1.11
***************
*** 24,32 ****
  #   version is still 5 times faster, though.
  # - Arguments more compliant with python standard
- #
- # This file implements the UUencode and UUdecode functions.
  
! # encode(in_file, out_file [,name, mode])
! # decode(in_file [, out_file, mode])
  
  import binascii
--- 24,33 ----
  #   version is still 5 times faster, though.
  # - Arguments more compliant with python standard
  
! """Implementation of the UUencode and UUdecode functions.
! 
! encode(in_file, out_file [,name, mode])
! decode(in_file [, out_file, mode])
! """
  
  import binascii

Index: wave.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/wave.py,v
retrieving revision 1.8
retrieving revision 1.9
diff -C2 -r1.8 -r1.9
*** wave.py	1999/08/26 15:50:43	1.8
--- wave.py	2000/02/04 15:28:42	1.9
***************
*** 1,74 ****
! # Stuff to parse WAVE files.
! #
! # Usage.
! #
! # Reading WAVE files:
! #	f = wave.open(file, 'r')
! # where file is either the name of a file or an open file pointer.
! # The open file pointer must have methods read(), seek(), and close().
! # When the setpos() and rewind() methods are not used, the seek()
! # method is not  necessary.
! #
! # This returns an instance of a class with the following public methods:
! #	getnchannels()	-- returns number of audio channels (1 for
! #			   mono, 2 for stereo)
! #	getsampwidth()	-- returns sample width in bytes
! #	getframerate()	-- returns sampling frequency
! #	getnframes()	-- returns number of audio frames
! #	getcomptype()	-- returns compression type ('NONE' for linear samples)
! #	getcompname()	-- returns human-readable version of
! #			   compression type ('not compressed' linear samples)
! #	getparams()	-- returns a tuple consisting of all of the
! #			   above in the above order
! #	getmarkers()	-- returns None (for compatibility with the
! #			   aifc module)
! #	getmark(id)	-- raises an error since the mark does not
! #			   exist (for compatibility with the aifc module)
! #	readframes(n)	-- returns at most n frames of audio
! #	rewind()	-- rewind to the beginning of the audio stream
! #	setpos(pos)	-- seek to the specified position
! #	tell()		-- return the current position
! #	close()		-- close the instance (make it unusable)
! # The position returned by tell() and the position given to setpos()
! # are compatible and have nothing to do with the actual postion in the
! # file.
! # The close() method is called automatically when the class instance
! # is destroyed.
! #
! # Writing WAVE files:
! #	f = wave.open(file, 'w')
! # where file is either the name of a file or an open file pointer.
! # The open file pointer must have methods write(), tell(), seek(), and
! # close().
! #
! # This returns an instance of a class with the following public methods:
! #	setnchannels(n)	-- set the number of channels
! #	setsampwidth(n)	-- set the sample width
! #	setframerate(n)	-- set the frame rate
! #	setnframes(n)	-- set the number of frames
! #	setcomptype(type, name)
! #			-- set the compression type and the
! #			   human-readable compression type
! #	setparams(tuple)
! #			-- set all parameters at once
! #	tell()		-- return current position in output file
! #	writeframesraw(data)
! #			-- write audio frames without pathing up the
! #			   file header
! #	writeframes(data)
! #			-- write audio frames and patch up the file header
! #	close()		-- patch up the file header and close the
! #			   output file
! # You should set the parameters before the first writeframesraw or
! # writeframes.  The total number of frames does not need to be set,
! # but when it is set to the correct value, the header does not have to
! # be patched up.
! # It is best to first set all parameters, perhaps possibly the
! # compression type, and then write audio frames using writeframesraw.
! # When all frames have been written, either call writeframes('') or
! # close() to patch up the sizes in the header.
! # The close() method is called automatically when the class instance
! # is destroyed.
  
  import __builtin__
  
--- 1,75 ----
! """Stuff to parse WAVE files.
  
+ Usage.
+ 
+ Reading WAVE files:
+       f = wave.open(file, 'r')
+ where file is either the name of a file or an open file pointer.
+ The open file pointer must have methods read(), seek(), and close().
+ When the setpos() and rewind() methods are not used, the seek()
+ method is not  necessary.
+ 
+ This returns an instance of a class with the following public methods:
+       getnchannels()  -- returns number of audio channels (1 for
+                          mono, 2 for stereo)
+       getsampwidth()  -- returns sample width in bytes
+       getframerate()  -- returns sampling frequency
+       getnframes()    -- returns number of audio frames
+       getcomptype()   -- returns compression type ('NONE' for linear samples)
+       getcompname()   -- returns human-readable version of
+                          compression type ('not compressed' linear samples)
+       getparams()     -- returns a tuple consisting of all of the
+                          above in the above order
+       getmarkers()    -- returns None (for compatibility with the
+                          aifc module)
+       getmark(id)     -- raises an error since the mark does not
+                          exist (for compatibility with the aifc module)
+       readframes(n)   -- returns at most n frames of audio
+       rewind()        -- rewind to the beginning of the audio stream
+       setpos(pos)     -- seek to the specified position
+       tell()          -- return the current position
+       close()         -- close the instance (make it unusable)
+ The position returned by tell() and the position given to setpos()
+ are compatible and have nothing to do with the actual postion in the
+ file.
+ The close() method is called automatically when the class instance
+ is destroyed.
+ 
+ Writing WAVE files:
+       f = wave.open(file, 'w')
+ where file is either the name of a file or an open file pointer.
+ The open file pointer must have methods write(), tell(), seek(), and
+ close().
+ 
+ This returns an instance of a class with the following public methods:
+       setnchannels(n) -- set the number of channels
+       setsampwidth(n) -- set the sample width
+       setframerate(n) -- set the frame rate
+       setnframes(n)   -- set the number of frames
+       setcomptype(type, name)
+                       -- set the compression type and the
+                          human-readable compression type
+       setparams(tuple)
+                       -- set all parameters at once
+       tell()          -- return current position in output file
+       writeframesraw(data)
+                       -- write audio frames without pathing up the
+                          file header
+       writeframes(data)
+                       -- write audio frames and patch up the file header
+       close()         -- patch up the file header and close the
+                          output file
+ You should set the parameters before the first writeframesraw or
+ writeframes.  The total number of frames does not need to be set,
+ but when it is set to the correct value, the header does not have to
+ be patched up.
+ It is best to first set all parameters, perhaps possibly the
+ compression type, and then write audio frames using writeframesraw.
+ When all frames have been written, either call writeframes('') or
+ close() to patch up the sizes in the header.
+ The close() method is called automatically when the class instance
+ is destroyed.
+ """
+ 
  import __builtin__
  
***************
*** 82,471 ****
  import struct
  if struct.pack("h", 1) == "\000\001":
! 	big_endian = 1
  else:
! 	big_endian = 0
  
  from chunk import Chunk
  
  class Wave_read:
! 	# Variables used in this class:
! 	#
! 	# These variables are available to the user though appropriate
! 	# methods of this class:
! 	# _file -- the open file with methods read(), close(), and seek()
! 	#		set through the __init__() method
! 	# _nchannels -- the number of audio channels
! 	#		available through the getnchannels() method
! 	# _nframes -- the number of audio frames
! 	#		available through the getnframes() method
! 	# _sampwidth -- the number of bytes per audio sample
! 	#		available through the getsampwidth() method
! 	# _framerate -- the sampling frequency
! 	#		available through the getframerate() method
! 	# _comptype -- the AIFF-C compression type ('NONE' if AIFF)
! 	#		available through the getcomptype() method
! 	# _compname -- the human-readable AIFF-C compression type
! 	#		available through the getcomptype() method
! 	# _soundpos -- the position in the audio stream
! 	#		available through the tell() method, set through the
! 	#		setpos() method
! 	#
! 	# These variables are used internally only:
! 	# _fmt_chunk_read -- 1 iff the FMT chunk has been read
! 	# _data_seek_needed -- 1 iff positioned correctly in audio
! 	#		file for readframes()
! 	# _data_chunk -- instantiation of a chunk class for the DATA chunk
! 	# _framesize -- size of one frame in the file
! 
! 	def initfp(self, file):
! 		self._convert = None
! 		self._soundpos = 0
! 		self._file = Chunk(file, bigendian = 0)
! 		if self._file.getname() != 'RIFF':
! 			raise Error, 'file does not start with RIFF id'
! 		if self._file.read(4) != 'WAVE':
! 			raise Error, 'not a WAVE file'
! 		self._fmt_chunk_read = 0
! 		self._data_chunk = None
! 		while 1:
! 			self._data_seek_needed = 1
! 			try:
! 				chunk = Chunk(self._file, bigendian = 0)
! 			except EOFError:
! 				break
! 			chunkname = chunk.getname()
! 			if chunkname == 'fmt ':
! 				self._read_fmt_chunk(chunk)
! 				self._fmt_chunk_read = 1
! 			elif chunkname == 'data':
! 				if not self._fmt_chunk_read:
! 					raise Error, 'data chunk before fmt chunk'
! 				self._data_chunk = chunk
! 				self._nframes = chunk.chunksize / self._framesize
! 				self._data_seek_needed = 0
! 				break
! 			chunk.skip()
! 		if not self._fmt_chunk_read or not self._data_chunk:
! 			raise Error, 'fmt chunk and/or data chunk missing'
! 
! 	def __init__(self, f):
! 		if type(f) == type(''):
! 			f = __builtin__.open(f, 'rb')
! 		# else, assume it is an open file object already
! 		self.initfp(f)
! 
! 	#
! 	# User visible methods.
! 	#
! 	def getfp(self):
! 		return self._file
! 
! 	def rewind(self):
! 		self._data_seek_needed = 1
! 		self._soundpos = 0
! 
! 	def close(self):
! 		self._file = None
! 
! 	def tell(self):
! 		return self._soundpos
! 
! 	def getnchannels(self):
! 		return self._nchannels
! 
! 	def getnframes(self):
! 		return self._nframes
! 
! 	def getsampwidth(self):
! 		return self._sampwidth
! 
! 	def getframerate(self):
! 		return self._framerate
! 
! 	def getcomptype(self):
! 		return self._comptype
! 
! 	def getcompname(self):
! 		return self._compname
! 
! 	def getparams(self):
! 		return self.getnchannels(), self.getsampwidth(), \
! 			  self.getframerate(), self.getnframes(), \
! 			  self.getcomptype(), self.getcompname()
! 
! 	def getmarkers(self):
! 		return None
! 
! 	def getmark(self, id):
! 		raise Error, 'no marks'
! 
! 	def setpos(self, pos):
! 		if pos < 0 or pos > self._nframes:
! 			raise Error, 'position not in range'
! 		self._soundpos = pos
! 		self._data_seek_needed = 1
! 
! 	def readframes(self, nframes):
! 		if self._data_seek_needed:
! 			self._data_chunk.seek(0, 0)
! 			pos = self._soundpos * self._framesize
! 			if pos:
! 				self._data_chunk.seek(pos, 0)
! 			self._data_seek_needed = 0
! 		if nframes == 0:
! 			return ''
! 		if self._sampwidth > 1 and big_endian:
! 			# unfortunately the fromfile() method does not take
! 			# something that only looks like a file object, so
! 			# we have to reach into the innards of the chunk object
! 			import array
! 			chunk = self._data_chunk
! 			data = array.array(_array_fmts[self._sampwidth])
! 			nitems = nframes * self._nchannels
! 			if nitems * self._sampwidth > chunk.chunksize - chunk.size_read:
! 				nitems = (chunk.chunksize - chunk.size_read) / self._sampwidth
! 			data.fromfile(chunk.file.file, nitems)
! 			# "tell" data chunk how much was read
! 			chunk.size_read = chunk.size_read + nitems * self._sampwidth
! 			# do the same for the outermost chunk
! 			chunk = chunk.file
! 			chunk.size_read = chunk.size_read + nitems * self._sampwidth
! 			data.byteswap()
! 			data = data.tostring()
! 		else:
! 			data = self._data_chunk.read(nframes * self._framesize)
! 		if self._convert and data:
! 			data = self._convert(data)
! 		self._soundpos = self._soundpos + len(data) / (self._nchannels * self._sampwidth)
! 		return data
! 
! 	#
! 	# Internal methods.
! 	#
! 
! 	def _read_fmt_chunk(self, chunk):
! 		wFormatTag, self._nchannels, self._framerate, dwAvgBytesPerSec, wBlockAlign = struct.unpack('<hhllh', chunk.read(14))
! 		if wFormatTag == WAVE_FORMAT_PCM:
! 			sampwidth = struct.unpack('<h', chunk.read(2))[0]
! 			self._sampwidth = (sampwidth + 7) / 8
! 		else:
! 			raise Error, 'unknown format: ' + `wFormatTag`
! 		self._framesize = self._nchannels * self._sampwidth
! 		self._comptype = 'NONE'
! 		self._compname = 'not compressed'
  
  class Wave_write:
! 	# Variables used in this class:
! 	#
! 	# These variables are user settable through appropriate methods
! 	# of this class:
! 	# _file -- the open file with methods write(), close(), tell(), seek()
! 	#		set through the __init__() method
! 	# _comptype -- the AIFF-C compression type ('NONE' in AIFF)
! 	#		set through the setcomptype() or setparams() method
! 	# _compname -- the human-readable AIFF-C compression type
! 	#		set through the setcomptype() or setparams() method
! 	# _nchannels -- the number of audio channels
! 	#		set through the setnchannels() or setparams() method
! 	# _sampwidth -- the number of bytes per audio sample
! 	#		set through the setsampwidth() or setparams() method
! 	# _framerate -- the sampling frequency
! 	#		set through the setframerate() or setparams() method
! 	# _nframes -- the number of audio frames written to the header
! 	#		set through the setnframes() or setparams() method
! 	#
! 	# These variables are used internally only:
! 	# _datalength -- the size of the audio samples written to the header
! 	# _nframeswritten -- the number of frames actually written
! 	# _datawritten -- the size of the audio samples actually written
! 
! 	def __init__(self, f):
! 		if type(f) == type(''):
! 			f = __builtin__.open(f, 'wb')
! 		self.initfp(f)
! 
! 	def initfp(self, file):
! 		self._file = file
! 		self._convert = None
! 		self._nchannels = 0
! 		self._sampwidth = 0
! 		self._framerate = 0
! 		self._nframes = 0
! 		self._nframeswritten = 0
! 		self._datawritten = 0
! 		self._datalength = 0
! 
! 	def __del__(self):
! 		if self._file:
! 			self.close()
! 
! 	#
! 	# User visible methods.
! 	#
! 	def setnchannels(self, nchannels):
! 		if self._datawritten:
! 			raise Error, 'cannot change parameters after starting to write'
! 		if nchannels < 1:
! 			raise Error, 'bad # of channels'
! 		self._nchannels = nchannels
! 
! 	def getnchannels(self):
! 		if not self._nchannels:
! 			raise Error, 'number of channels not set'
! 		return self._nchannels
! 
! 	def setsampwidth(self, sampwidth):
! 		if self._datawritten:
! 			raise Error, 'cannot change parameters after starting to write'
! 		if sampwidth < 1 or sampwidth > 4:
! 			raise Error, 'bad sample width'
! 		self._sampwidth = sampwidth
! 
! 	def getsampwidth(self):
! 		if not self._sampwidth:
! 			raise Error, 'sample width not set'
! 		return self._sampwidth
! 
! 	def setframerate(self, framerate):
! 		if self._datawritten:
! 			raise Error, 'cannot change parameters after starting to write'
! 		if framerate <= 0:
! 			raise Error, 'bad frame rate'
! 		self._framerate = framerate
! 
! 	def getframerate(self):
! 		if not self._framerate:
! 			raise Error, 'frame rate not set'
! 		return self._framerate
! 
! 	def setnframes(self, nframes):
! 		if self._datawritten:
! 			raise Error, 'cannot change parameters after starting to write'
! 		self._nframes = nframes
! 
! 	def getnframes(self):
! 		return self._nframeswritten
! 
! 	def setcomptype(self, comptype, compname):
! 		if self._datawritten:
! 			raise Error, 'cannot change parameters after starting to write'
! 		if comptype not in ('NONE',):
! 			raise Error, 'unsupported compression type'
! 		self._comptype = comptype
! 		self._compname = compname
! 
! 	def getcomptype(self):
! 		return self._comptype
! 
! 	def getcompname(self):
! 		return self._compname
! 
! 	def setparams(self, (nchannels, sampwidth, framerate, nframes, comptype, compname)):
! 		if self._datawritten:
! 			raise Error, 'cannot change parameters after starting to write'
! 		self.setnchannels(nchannels)
! 		self.setsampwidth(sampwidth)
! 		self.setframerate(framerate)
! 		self.setnframes(nframes)
! 		self.setcomptype(comptype, compname)
! 
! 	def getparams(self):
! 		if not self._nchannels or not self._sampwidth or not self._framerate:
! 			raise Error, 'not all parameters set'
! 		return self._nchannels, self._sampwidth, self._framerate, \
! 			  self._nframes, self._comptype, self._compname
! 
! 	def setmark(self, id, pos, name):
! 		raise Error, 'setmark() not supported'
! 
! 	def getmark(self, id):
! 		raise Error, 'no marks'
! 
! 	def getmarkers(self):
! 		return None
! 				
! 	def tell(self):
! 		return self._nframeswritten
! 
! 	def writeframesraw(self, data):
! 		self._ensure_header_written(len(data))
! 		nframes = len(data) / (self._sampwidth * self._nchannels)
! 		if self._convert:
! 			data = self._convert(data)
! 		if self._sampwidth > 1 and big_endian:
! 			import array
! 			data = array.array(_array_fmts[self._sampwidth], data)
! 			data.byteswap()
! 			data.tofile(self._file)
! 			self._datawritten = self._datawritten + len(data) * self._sampwidth
! 		else:
! 			self._file.write(data)
! 			self._datawritten = self._datawritten + len(data)
! 		self._nframeswritten = self._nframeswritten + nframes
! 
! 	def writeframes(self, data):
! 		self.writeframesraw(data)
! 		if self._datalength != self._datawritten:
! 			self._patchheader()
! 
! 	def close(self):
! 		self._ensure_header_written(0)
! 		if self._datalength != self._datawritten:
! 			self._patchheader()
! 		self._file.flush()
! 		self._file = None
! 
! 	#
! 	# Internal methods.
! 	#
! 
! 	def _ensure_header_written(self, datasize):
! 		if not self._datawritten:
! 			if not self._nchannels:
! 				raise Error, '# channels not specified'
! 			if not self._sampwidth:
! 				raise Error, 'sample width not specified'
! 			if not self._framerate:
! 				raise Error, 'sampling rate not specified'
! 			self._write_header(datasize)
! 
! 	def _write_header(self, initlength):
! 		self._file.write('RIFF')
! 		if not self._nframes:
! 			self._nframes = initlength / (self._nchannels * self._sampwidth)
! 		self._datalength = self._nframes * self._nchannels * self._sampwidth
! 		self._form_length_pos = self._file.tell()
! 		self._file.write(struct.pack('<lsslhhllhhs',
! 			36 + self._datalength, 'WAVE', 'fmt ', 16,
! 			WAVE_FORMAT_PCM, self._nchannels, self._framerate,
! 			self._nchannels * self._framerate * self._sampwidth,
! 			self._nchannels * self._sampwidth,
! 			self._sampwidth * 8, 'data'))
! 		self._data_length_pos = self._file.tell()
! 		self._file.write(struct.pack('<l', self._datalength))
! 
! 	def _patchheader(self):
! 		if self._datawritten == self._datalength:
! 			return
! 		curpos = self._file.tell()
! 		self._file.seek(self._form_length_pos, 0)
! 		self._file.write(struct.pack('<l', 36 + self._datawritten))
! 		self._file.seek(self._data_length_pos, 0)
! 		self._file.write(struct.pack('<l', self._datawritten))
! 		self._file.seek(curpos, 0)
! 		self._datalength = self._datawritten
  
  def open(f, mode=None):
! 	if mode is None:
! 		if hasattr(f, 'mode'):
! 			mode = f.mode
! 		else:
! 			mode = 'rb'
! 	if mode in ('r', 'rb'):
! 		return Wave_read(f)
! 	elif mode in ('w', 'wb'):
! 		return Wave_write(f)
! 	else:
! 		raise Error, "mode must be 'r', 'rb', 'w', or 'wb'"
  
  openfp = open # B/W compatibility
--- 83,474 ----
  import struct
  if struct.pack("h", 1) == "\000\001":
!     big_endian = 1
  else:
!     big_endian = 0
  
  from chunk import Chunk
  
  class Wave_read:
!     """Variables used in this class:
  
+     These variables are available to the user though appropriate
+     methods of this class:
+     _file -- the open file with methods read(), close(), and seek()
+               set through the __init__() method
+     _nchannels -- the number of audio channels
+               available through the getnchannels() method
+     _nframes -- the number of audio frames
+               available through the getnframes() method
+     _sampwidth -- the number of bytes per audio sample
+               available through the getsampwidth() method
+     _framerate -- the sampling frequency
+               available through the getframerate() method
+     _comptype -- the AIFF-C compression type ('NONE' if AIFF)
+               available through the getcomptype() method
+     _compname -- the human-readable AIFF-C compression type
+               available through the getcomptype() method
+     _soundpos -- the position in the audio stream
+               available through the tell() method, set through the
+               setpos() method
+ 
+     These variables are used internally only:
+     _fmt_chunk_read -- 1 iff the FMT chunk has been read
+     _data_seek_needed -- 1 iff positioned correctly in audio
+               file for readframes()
+     _data_chunk -- instantiation of a chunk class for the DATA chunk
+     _framesize -- size of one frame in the file
+     """
+ 
+     def initfp(self, file):
+         self._convert = None
+         self._soundpos = 0
+         self._file = Chunk(file, bigendian = 0)
+         if self._file.getname() != 'RIFF':
+             raise Error, 'file does not start with RIFF id'
+         if self._file.read(4) != 'WAVE':
+             raise Error, 'not a WAVE file'
+         self._fmt_chunk_read = 0
+         self._data_chunk = None
+         while 1:
+             self._data_seek_needed = 1
+             try:
+                 chunk = Chunk(self._file, bigendian = 0)
+             except EOFError:
+                 break
+             chunkname = chunk.getname()
+             if chunkname == 'fmt ':
+                 self._read_fmt_chunk(chunk)
+                 self._fmt_chunk_read = 1
+             elif chunkname == 'data':
+                 if not self._fmt_chunk_read:
+                     raise Error, 'data chunk before fmt chunk'
+                 self._data_chunk = chunk
+                 self._nframes = chunk.chunksize / self._framesize
+                 self._data_seek_needed = 0
+                 break
+             chunk.skip()
+         if not self._fmt_chunk_read or not self._data_chunk:
+             raise Error, 'fmt chunk and/or data chunk missing'
+ 
+     def __init__(self, f):
+         if type(f) == type(''):
+             f = __builtin__.open(f, 'rb')
+         # else, assume it is an open file object already
+         self.initfp(f)
+ 
+     #
+     # User visible methods.
+     #
+     def getfp(self):
+         return self._file
+ 
+     def rewind(self):
+         self._data_seek_needed = 1
+         self._soundpos = 0
+ 
+     def close(self):
+         self._file = None
+ 
+     def tell(self):
+         return self._soundpos
+ 
+     def getnchannels(self):
+         return self._nchannels
+ 
+     def getnframes(self):
+         return self._nframes
+ 
+     def getsampwidth(self):
+         return self._sampwidth
+ 
+     def getframerate(self):
+         return self._framerate
+ 
+     def getcomptype(self):
+         return self._comptype
+ 
+     def getcompname(self):
+         return self._compname
+ 
+     def getparams(self):
+         return self.getnchannels(), self.getsampwidth(), \
+                self.getframerate(), self.getnframes(), \
+                self.getcomptype(), self.getcompname()
+ 
+     def getmarkers(self):
+         return None
+ 
+     def getmark(self, id):
+         raise Error, 'no marks'
+ 
+     def setpos(self, pos):
+         if pos < 0 or pos > self._nframes:
+             raise Error, 'position not in range'
+         self._soundpos = pos
+         self._data_seek_needed = 1
+ 
+     def readframes(self, nframes):
+         if self._data_seek_needed:
+             self._data_chunk.seek(0, 0)
+             pos = self._soundpos * self._framesize
+             if pos:
+                 self._data_chunk.seek(pos, 0)
+             self._data_seek_needed = 0
+         if nframes == 0:
+             return ''
+         if self._sampwidth > 1 and big_endian:
+             # unfortunately the fromfile() method does not take
+             # something that only looks like a file object, so
+             # we have to reach into the innards of the chunk object
+             import array
+             chunk = self._data_chunk
+             data = array.array(_array_fmts[self._sampwidth])
+             nitems = nframes * self._nchannels
+             if nitems * self._sampwidth > chunk.chunksize - chunk.size_read:
+                 nitems = (chunk.chunksize - chunk.size_read) / self._sampwidth
+             data.fromfile(chunk.file.file, nitems)
+             # "tell" data chunk how much was read
+             chunk.size_read = chunk.size_read + nitems * self._sampwidth
+             # do the same for the outermost chunk
+             chunk = chunk.file
+             chunk.size_read = chunk.size_read + nitems * self._sampwidth
+             data.byteswap()
+             data = data.tostring()
+         else:
+             data = self._data_chunk.read(nframes * self._framesize)
+         if self._convert and data:
+             data = self._convert(data)
+         self._soundpos = self._soundpos + len(data) / (self._nchannels * self._sampwidth)
+         return data
+ 
+     #
+     # Internal methods.
+     #
+ 
+     def _read_fmt_chunk(self, chunk):
+         wFormatTag, self._nchannels, self._framerate, dwAvgBytesPerSec, wBlockAlign = struct.unpack('<hhllh', chunk.read(14))
+         if wFormatTag == WAVE_FORMAT_PCM:
+             sampwidth = struct.unpack('<h', chunk.read(2))[0]
+             self._sampwidth = (sampwidth + 7) / 8
+         else:
+             raise Error, 'unknown format: ' + `wFormatTag`
+         self._framesize = self._nchannels * self._sampwidth
+         self._comptype = 'NONE'
+         self._compname = 'not compressed'
+ 
  class Wave_write:
!     """Variables used in this class:
! 
!     These variables are user settable through appropriate methods
!     of this class:
!     _file -- the open file with methods write(), close(), tell(), seek()
!               set through the __init__() method
!     _comptype -- the AIFF-C compression type ('NONE' in AIFF)
!               set through the setcomptype() or setparams() method
!     _compname -- the human-readable AIFF-C compression type
!               set through the setcomptype() or setparams() method
!     _nchannels -- the number of audio channels
!               set through the setnchannels() or setparams() method
!     _sampwidth -- the number of bytes per audio sample
!               set through the setsampwidth() or setparams() method
!     _framerate -- the sampling frequency
!               set through the setframerate() or setparams() method
!     _nframes -- the number of audio frames written to the header
!               set through the setnframes() or setparams() method
! 
!     These variables are used internally only:
!     _datalength -- the size of the audio samples written to the header
!     _nframeswritten -- the number of frames actually written
!     _datawritten -- the size of the audio samples actually written
!     """
! 
!     def __init__(self, f):
!         if type(f) == type(''):
!             f = __builtin__.open(f, 'wb')
!         self.initfp(f)
! 
!     def initfp(self, file):
!         self._file = file
!         self._convert = None
!         self._nchannels = 0
!         self._sampwidth = 0
!         self._framerate = 0
!         self._nframes = 0
!         self._nframeswritten = 0
!         self._datawritten = 0
!         self._datalength = 0
! 
!     def __del__(self):
!         if self._file:
!             self.close()
! 
!     #
!     # User visible methods.
!     #
!     def setnchannels(self, nchannels):
!         if self._datawritten:
!             raise Error, 'cannot change parameters after starting to write'
!         if nchannels < 1:
!             raise Error, 'bad # of channels'
!         self._nchannels = nchannels
! 
!     def getnchannels(self):
!         if not self._nchannels:
!             raise Error, 'number of channels not set'
!         return self._nchannels
! 
!     def setsampwidth(self, sampwidth):
!         if self._datawritten:
!             raise Error, 'cannot change parameters after starting to write'
!         if sampwidth < 1 or sampwidth > 4:
!             raise Error, 'bad sample width'
!         self._sampwidth = sampwidth
! 
!     def getsampwidth(self):
!         if not self._sampwidth:
!             raise Error, 'sample width not set'
!         return self._sampwidth
! 
!     def setframerate(self, framerate):
!         if self._datawritten:
!             raise Error, 'cannot change parameters after starting to write'
!         if framerate <= 0:
!             raise Error, 'bad frame rate'
!         self._framerate = framerate
! 
!     def getframerate(self):
!         if not self._framerate:
!             raise Error, 'frame rate not set'
!         return self._framerate
! 
!     def setnframes(self, nframes):
!         if self._datawritten:
!             raise Error, 'cannot change parameters after starting to write'
!         self._nframes = nframes
! 
!     def getnframes(self):
!         return self._nframeswritten
! 
!     def setcomptype(self, comptype, compname):
!         if self._datawritten:
!             raise Error, 'cannot change parameters after starting to write'
!         if comptype not in ('NONE',):
!             raise Error, 'unsupported compression type'
!         self._comptype = comptype
!         self._compname = compname
! 
!     def getcomptype(self):
!         return self._comptype
! 
!     def getcompname(self):
!         return self._compname
! 
!     def setparams(self, (nchannels, sampwidth, framerate, nframes, comptype, compname)):
!         if self._datawritten:
!             raise Error, 'cannot change parameters after starting to write'
!         self.setnchannels(nchannels)
!         self.setsampwidth(sampwidth)
!         self.setframerate(framerate)
!         self.setnframes(nframes)
!         self.setcomptype(comptype, compname)
! 
!     def getparams(self):
!         if not self._nchannels or not self._sampwidth or not self._framerate:
!             raise Error, 'not all parameters set'
!         return self._nchannels, self._sampwidth, self._framerate, \
!               self._nframes, self._comptype, self._compname
! 
!     def setmark(self, id, pos, name):
!         raise Error, 'setmark() not supported'
! 
!     def getmark(self, id):
!         raise Error, 'no marks'
! 
!     def getmarkers(self):
!         return None
!                 
!     def tell(self):
!         return self._nframeswritten
! 
!     def writeframesraw(self, data):
!         self._ensure_header_written(len(data))
!         nframes = len(data) / (self._sampwidth * self._nchannels)
!         if self._convert:
!             data = self._convert(data)
!         if self._sampwidth > 1 and big_endian:
!             import array
!             data = array.array(_array_fmts[self._sampwidth], data)
!             data.byteswap()
!             data.tofile(self._file)
!             self._datawritten = self._datawritten + len(data) * self._sampwidth
!         else:
!             self._file.write(data)
!             self._datawritten = self._datawritten + len(data)
!         self._nframeswritten = self._nframeswritten + nframes
! 
!     def writeframes(self, data):
!         self.writeframesraw(data)
!         if self._datalength != self._datawritten:
!             self._patchheader()
! 
!     def close(self):
!         self._ensure_header_written(0)
!         if self._datalength != self._datawritten:
!             self._patchheader()
!         self._file.flush()
!         self._file = None
! 
!     #
!     # Internal methods.
!     #
! 
!     def _ensure_header_written(self, datasize):
!         if not self._datawritten:
!             if not self._nchannels:
!                 raise Error, '# channels not specified'
!             if not self._sampwidth:
!                 raise Error, 'sample width not specified'
!             if not self._framerate:
!                 raise Error, 'sampling rate not specified'
!             self._write_header(datasize)
! 
!     def _write_header(self, initlength):
!         self._file.write('RIFF')
!         if not self._nframes:
!             self._nframes = initlength / (self._nchannels * self._sampwidth)
!         self._datalength = self._nframes * self._nchannels * self._sampwidth
!         self._form_length_pos = self._file.tell()
!         self._file.write(struct.pack('<lsslhhllhhs',
!             36 + self._datalength, 'WAVE', 'fmt ', 16,
!             WAVE_FORMAT_PCM, self._nchannels, self._framerate,
!             self._nchannels * self._framerate * self._sampwidth,
!             self._nchannels * self._sampwidth,
!             self._sampwidth * 8, 'data'))
!         self._data_length_pos = self._file.tell()
!         self._file.write(struct.pack('<l', self._datalength))
! 
!     def _patchheader(self):
!         if self._datawritten == self._datalength:
!             return
!         curpos = self._file.tell()
!         self._file.seek(self._form_length_pos, 0)
!         self._file.write(struct.pack('<l', 36 + self._datawritten))
!         self._file.seek(self._data_length_pos, 0)
!         self._file.write(struct.pack('<l', self._datawritten))
!         self._file.seek(curpos, 0)
!         self._datalength = self._datawritten
  
  def open(f, mode=None):
!     if mode is None:
!         if hasattr(f, 'mode'):
!             mode = f.mode
!         else:
!             mode = 'rb'
!     if mode in ('r', 'rb'):
!         return Wave_read(f)
!     elif mode in ('w', 'wb'):
!         return Wave_write(f)
!     else:
!         raise Error, "mode must be 'r', 'rb', 'w', or 'wb'"
  
  openfp = open # B/W compatibility

Index: whrandom.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/whrandom.py,v
retrieving revision 1.14
retrieving revision 1.15
diff -C2 -r1.14 -r1.15
*** whrandom.py	1998/08/10 20:07:53	1.14
--- whrandom.py	2000/02/04 15:28:42	1.15
***************
*** 1,53 ****
! #	WICHMANN-HILL RANDOM NUMBER GENERATOR
! #
! #	Wichmann, B. A. & Hill, I. D. (1982)
! #	Algorithm AS 183: 
! #	An efficient and portable pseudo-random number generator
! #	Applied Statistics 31 (1982) 188-190
! #
! #	see also: 
! #		Correction to Algorithm AS 183
! #		Applied Statistics 33 (1984) 123  
! #
! #		McLeod, A. I. (1985)
! #		A remark on Algorithm AS 183 
! #		Applied Statistics 34 (1985),198-200
! #
! #
! #	USE:
! #	whrandom.random()	yields double precision random numbers 
! #				uniformly distributed between 0 and 1.
! #
! #	whrandom.seed(x, y, z)	must be called before whrandom.random()
! #				to seed the generator
! #
! #	There is also an interface to create multiple independent
! #	random generators, and to choose from other ranges.
! 
! 
! #	Translated by Guido van Rossum from C source provided by
! #	Adrian Baddeley.
! 
! 
! # Multi-threading note: the random number generator used here is not
! # thread-safe; it is possible that nearly simultaneous calls in
! # different theads return the same random value.  To avoid this, you
! # have to use a lock around all calls.  (I didn't want to slow this
! # down in the serial case by using a lock here.)
  
  
  class whrandom:
- 	#
- 	# Initialize an instance.
- 	# Without arguments, initialize from current time.
- 	# With arguments (x, y, z), initialize from them.
- 	#
  	def __init__(self, x = 0, y = 0, z = 0):
  		self.seed(x, y, z)
! 	#
! 	# Set the seed from (x, y, z).
! 	# These must be integers in the range [0, 256).
! 	#
  	def seed(self, x = 0, y = 0, z = 0):
  		if not type(x) == type(y) == type(z) == type(0):
  			raise TypeError, 'seeds must be integers'
--- 1,51 ----
! """Wichman-Hill random number generator.
  
+ Wichmann, B. A. & Hill, I. D. (1982)
+ Algorithm AS 183: 
+ An efficient and portable pseudo-random number generator
+ Applied Statistics 31 (1982) 188-190
  
+ see also: 
+         Correction to Algorithm AS 183
+         Applied Statistics 33 (1984) 123  
+ 
+         McLeod, A. I. (1985)
+         A remark on Algorithm AS 183 
+         Applied Statistics 34 (1985),198-200
+ 
+ 
+ USE:
+ whrandom.random()       yields double precision random numbers 
+                         uniformly distributed between 0 and 1.
+ 
+ whrandom.seed(x, y, z)  must be called before whrandom.random()
+                         to seed the generator
+ 
+ There is also an interface to create multiple independent
+ random generators, and to choose from other ranges.
+ 
+ 
+ Translated by Guido van Rossum from C source provided by
+ Adrian Baddeley.
+ 
+ 
+ 
+ Multi-threading note: the random number generator used here is not
+ thread-safe; it is possible that nearly simultaneous calls in
+ different theads return the same random value.  To avoid this, you
+ have to use a lock around all calls.  (I didn't want to slow this
+ down in the serial case by using a lock here.)
+ """
+ 
  class whrandom:
  	def __init__(self, x = 0, y = 0, z = 0):
+ 		"""Initialize an instance.
+ 		Without arguments, initialize from current time.
+ 		With arguments (x, y, z), initialize from them."""
  		self.seed(x, y, z)
! 
  	def seed(self, x = 0, y = 0, z = 0):
+ 		"""Set the seed from (x, y, z).
+ 		These must be integers in the range [0, 256)."""
  		if not type(x) == type(y) == type(z) == type(0):
  			raise TypeError, 'seeds must be integers'
***************
*** 64,71 ****
  		# Zero is a poor seed, so substitute 1
  		self._seed = (x or 1, y or 1, z or 1)
! 	#
! 	# Get the next random number in the range [0.0, 1.0).
! 	#
  	def random(self):
  		# This part is thread-unsafe:
  		# BEGIN CRITICAL SECTION
--- 62,68 ----
  		# Zero is a poor seed, so substitute 1
  		self._seed = (x or 1, y or 1, z or 1)
! 
  	def random(self):
+ 		"""Get the next random number in the range [0.0, 1.0)."""
  		# This part is thread-unsafe:
  		# BEGIN CRITICAL SECTION
***************
*** 80,107 ****
  		#
  		return (x/30269.0 + y/30307.0 + z/30323.0) % 1.0
! 	#
! 	# Get a random number in the range [a, b).
! 	#
  	def uniform(self, a, b):
  		return a + (b-a) * self.random()
! 	#
! 	# Get a random integer in the range [a, b] including both end points.
! 	# (Deprecated; use randrange below.)
! 	#
  	def randint(self, a, b):
  		return self.randrange(a, b+1)
! 	#
! 	# Choose a random element from a non-empty sequence.
! 	#
  	def choice(self, seq):
  		return seq[int(self.random() * len(seq))]
! 	#
! 	# Choose a random item from range([start,] step[, stop]).
! 	# This fixes the problem with randint() which includes the
! 	# endpoint; in Python this is usually not what you want.
! 	#
! 	def randrange(self, start, stop=None, step=1,
! 		      # Do not supply the following arguments
! 		      int=int, default=None):
  		# This code is a bit messy to make it fast for the
  		# common case while still doing adequate error checking
--- 77,99 ----
  		#
  		return (x/30269.0 + y/30307.0 + z/30323.0) % 1.0
! 
  	def uniform(self, a, b):
+ 		"""Get a random number in the range [a, b)."""
  		return a + (b-a) * self.random()
! 
  	def randint(self, a, b):
+ 		"""Get a random integer in the range [a, b] including both end points.
+ 		(Deprecated; use randrange below.)"""
  		return self.randrange(a, b+1)
! 
  	def choice(self, seq):
+ 		"""Choose a random element from a non-empty sequence."""
  		return seq[int(self.random() * len(seq))]
! 
! 	def randrange(self, start, stop=None, step=1, int=int, default=None):
! 		"""Choose a random item from range([start,] step[, stop]).
! 		This fixes the problem with randint() which includes the
! 		endpoint; in Python this is usually not what you want.
! 	    Do not supply the 'int' and 'default' arguments."""
  		# This code is a bit messy to make it fast for the
  		# common case while still doing adequate error checking
***************
*** 137,141 ****
  
  # Initialize from the current time
- #
  _inst = whrandom()
  seed = _inst.seed
--- 129,132 ----