From fdrake@weyr.cnri.reston.va.us Tue Feb 1 03:48:58 2000
From: fdrake@weyr.cnri.reston.va.us (Fred L. Drake)
Date: Mon, 31 Jan 2000 22:48:58 -0500 (EST)
Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libcode.tex,1.9,1.9.4.1 libcodeop.tex,1.1,1.1.2.1
Message-ID: <200002010348.WAA16800@weyr.cnri.reston.va.us>
Update of /projects/cvsroot/python/dist/src/Doc/lib
In directory weyr:/home/fdrake/projects/python/Doc-152p1/lib
Modified Files:
Tag: release152p1-patches
libcode.tex libcodeop.tex
Log Message:
Update descriptions.
For the code module, add information about the interpreter base classes,
since that's what is really interesting here.
Index: libcode.tex
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Doc/lib/libcode.tex,v
retrieving revision 1.9
retrieving revision 1.9.4.1
diff -C2 -r1.9 -r1.9.4.1
*** libcode.tex 1999/01/27 15:48:23 1.9
--- libcode.tex 2000/02/01 03:48:54 1.9.4.1
***************
*** 1,30 ****
\section{\module{code} ---
! Code object services.}
\declaremodule{standard}{code}
! \modulesynopsis{Code object services.}
! The \code{code} module defines operations pertaining to Python code
! objects. It defines the following function:
!
! \begin{funcdesc}{compile_command}{source, \optional{filename\optional{, symbol}}}
This function is useful for programs that want to emulate Python's
interpreter main loop (a.k.a. the read-eval-print loop). The tricky
part is to determine when the user has entered an incomplete command
! that can be completed by entering more text (as opposed to a complete
! command or a syntax error). This function \emph{almost} always makes
! the same decision as the real interpreter main loop.
!
! Arguments: \var{source} is the source string; \var{filename} is the
! optional filename from which source was read, defaulting to
! \code{''}; and \var{symbol} is the optional grammar start
! symbol, which should be either \code{'single'} (the default) or
! \code{'eval'}.
!
! Return a code object (the same as \code{compile(\var{source},
! \var{filename}, \var{symbol})}) if the command is complete and valid;
! return \code{None} if the command is incomplete; raise
! \exception{SyntaxError} if the command is a syntax error.
\end{funcdesc}
--- 1,173 ----
\section{\module{code} ---
! Interpreter base classes}
\declaremodule{standard}{code}
! \modulesynopsis{Base classes for interactive Python interpreters.}
! The \code{code} module provides facilities to implement
! read-eval-print loops in Python. Two classes and convenience
! functions are included which can be used to build applications which
! provide an interactive interpreter prompt.
!
!
! \begin{classdesc}{InteractiveInterpreter}{\optional{locals}}
! This class deals with parsing and interpreter state (the user's
! namespace); it does not deal with input buffering or prompting or
! input file naming (the filename is always passed in explicitly).
! The optional \var{locals} argument specifies the dictionary in
! which code will be executed; it defaults to a newly created
! dictionary with key \code{'__name__'} set to \code{'__console__'}
! and key \code{'__doc__'} set to \code{None}.
! \end{classdesc}
!
! \begin{classdesc}{InteractiveConsole}{\optional{locals\optional{, filename}}}
! Closely emulate the behavior of the interactive Python interpreter.
! This class builds on \class{InteractiveInterpreter} and adds
! prompting using the familiar \code{sys.ps1} and \code{sys.ps2}, and
! input buffering.
! \end{classdesc}
!
!
! \begin{funcdesc}{interact}{\optional{banner\optional{,
! readfunc\optional{, local}}}}
! Convenience function to run a read-eval-print loop. This creates a
! new instance of \class{InteractiveConsole} and sets \var{readfunc}
! to be used as the \method{raw_input()} method, if provided. If
! \var{local} is provided, it is passed to the
! \class{InteractiveConsole} constructor for use as the default
! namespace for the interpreter loop. The \method{interact()} method
! of the instance is then run with \var{banner} passed as the banner
! to use, if provided. The console object is discarded after use.
! \end{funcdesc}
! \begin{funcdesc}{compile_command}{source\optional{,
! filename\optional{, symbol}}}
This function is useful for programs that want to emulate Python's
interpreter main loop (a.k.a. the read-eval-print loop). The tricky
part is to determine when the user has entered an incomplete command
! that can be completed by entering more text (as opposed to a
! complete command or a syntax error). This function
! \emph{almost} always makes the same decision as the real interpreter
! main loop.
!
! \var{source} is the source string; \var{filename} is the optional
! filename from which source was read, defaulting to \code{''};
! and \var{symbol} is the optional grammar start symbol, which should
! be either \code{'single'} (the default) or \code{'eval'}.
!
! Returns a code object (the same as \code{compile(\var{source},
! \var{filename}, \var{symbol})}) if the command is complete and
! valid; \code{None} if the command is incomplete; raises
! \exception{SyntaxError} if the command is complete and contains a
! syntax error, or raises \exception{OverflowError} if the command
! includes a numeric constant which exceeds the range of the
! appropriate numeric type.
\end{funcdesc}
+
+
+ \subsection{Interactive Interpreter Objects
+ \label{interpreter-objects}}
+
+ \begin{methoddesc}{runsource}{source\optional{, filename\optional{, symbol}}}
+ Compile and run some source in the interpreter.
+ Arguments are the same as for \function{compile_command()}; the
+ default for \var{filename} is \code{''}, and for
+ \var{symbol} is \code{'single'}. One several things can happen:
+
+ \begin{itemize}
+ \item
+ The input is incorrect; \function{compile_command()} raised an
+ exception (\exception{SyntaxError} or \exception{OverflowError}). A
+ syntax traceback will be printed by calling the
+ \method{showsyntaxerror()} method. \method{runsource()} returns
+ \code{0}.
+
+ \item
+ The input is incomplete, and more input is required;
+ \function{compile_command()} returned \code{None}.
+ \method{runsource()} returns \code{1}.
+
+ \item
+ The input is complete; \function{compile_command()} returned a code
+ object. The code is executed by calling the \method{runcode()} (which
+ also handles run-time exceptions, except for \exception{SystemExit}).
+ \method{runsource()} returns \code{0}.
+ \end{itemize}
+
+ The return value can be used to decide whether to use
+ \code{sys.ps1} or \code{sys.ps2} to prompt the next line.
+ \end{methoddesc}
+
+ \begin{methoddesc}{runcode}{code}
+ Execute a code object.
+ When an exception occurs, \method{showtraceback()} is called to
+ display a traceback. All exceptions are caught except
+ \exception{SystemExit}, which is allowed to propogate.
+
+ A note about \exception{KeyboardInterrupt}: this exception may occur
+ elsewhere in this code, and may not always be caught. The caller
+ should be prepared to deal with it.
+ \end{methoddesc}
+
+ \begin{methoddesc}{showsyntaxerror}{\optional{filename}}
+ Display the syntax error that just occurred. This does not display
+ a stack trace because there isn't one for syntax errors.
+ If \var{filename} is given, it is stuffed into the exception instead
+ of the default filename provided by Python's parser, because it
+ always uses \code{''} when reading from a string.
+ The output is written by the \method{write()} method.
+ \end{methoddesc}
+
+ \begin{methoddesc}{showtraceback}{}
+ Display the exception that just occurred. We remove the first stack
+ item because it is within the interpreter object implementation.
+ The output is written by the \method{write()} method.
+ \end{methoddesc}
+
+ \begin{methoddesc}{write}{data}
+ Write a string to standard output. Derived classes should override
+ this to provide the appropriate output handling as needed.
+ \end{methoddesc}
+
+
+ \subsection{Interactive Console Objects
+ \label{console-objects}}
+
+ The \class{InteractiveConsole} class is a subclass of
+ \class{InteractiveInterpreter}, and so offers all the methods of the
+ interpreter objects as well as the following additions.
+
+ \begin{methoddesc}{interact}{\optional{banner}}
+ Closely emulate the interactive Python console.
+ The optional banner argument specify the banner to print before the
+ first interaction; by default it prints a banner similar to the one
+ printed by the standard Python interpreter, followed by the class
+ name of the console object in parentheses (so as not to confuse this
+ with the real interpreter -- since it's so close!).
+ \end{methoddesc}
+
+ \begin{methoddesc}{push}{line}
+ Push a line of source text to the interpreter.
+ The line should not have a trailing newline; it may have internal
+ newlines. The line is appended to a buffer and the interpreter's
+ \method{runsource()} method is called with the concatenated contents
+ of the buffer as source. If this indicates that the command was
+ executed or invalid, the buffer is reset; otherwise, the command is
+ incomplete, and the buffer is left as it was after the line was
+ appended. The return value is \code{1} if more input is required,
+ \code{0} if the line was dealt with in some way (this is the same as
+ \method{runsource()}).
+ \end{methoddesc}
+
+ \begin{methoddesc}{resetbuffer}{}
+ Remove any unhandled source text from the input buffer.
+ \end{methoddesc}
+
+ \begin{methoddesc}{raw_input}{\optional{prompt}}
+ Write a prompt and read a line. The returned line does not include
+ the trailing newline. When the user enters the \EOF{} key sequence,
+ \exception{EOFError} is raised. The base implementation uses the
+ built-in function \function{raw_input()}; a subclass may replace this
+ with a different implementation.
+ \end{methoddesc}
Index: libcodeop.tex
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Doc/lib/libcodeop.tex,v
retrieving revision 1.1
retrieving revision 1.1.2.1
diff -C2 -r1.1 -r1.1.2.1
*** libcodeop.tex 1999/06/23 13:33:40 1.1
--- libcodeop.tex 2000/02/01 03:48:54 1.1.2.1
***************
*** 1,6 ****
- % LaTeXed from excellent doc-string.
\section{\module{codeop} ---
Compile Python code}
\declaremodule{standard}{codeop}
\sectionauthor{Moshe Zadka}{mzadka@geocities.com}
--- 1,7 ----
\section{\module{codeop} ---
Compile Python code}
+ % LaTeXed from excellent doc-string.
+
\declaremodule{standard}{codeop}
\sectionauthor{Moshe Zadka}{mzadka@geocities.com}
***************
*** 8,12 ****
The \module{codeop} module provides a function to compile Python code
! with hints on whether it certainly complete, possible complete or
definitely incomplete. This is used by the \refmodule{code} module
and should not normally be used directly.
--- 9,13 ----
The \module{codeop} module provides a function to compile Python code
! with hints on whether it is certainly complete, possibly complete or
definitely incomplete. This is used by the \refmodule{code} module
and should not normally be used directly.
***************
*** 16,38 ****
\begin{funcdesc}{compile_command}
{source\optional{, filename\optional{, symbol}}}
!
! Try to compile \var{source}, which should be a string of Python
! code. Return a code object if \var{source} is valid
Python code. In that case, the filename attribute of the code object
will be \var{filename}, which defaults to \code{''}.
!
! Return \code{None} if \var{source} is \emph{not} valid Python
code, but is a prefix of valid Python code.
-
- Raise an exception if there is a problem with \var{source}:
- \begin{itemize}
- \item \exception{SyntaxError}
- if there is invalid Python syntax.
- \item \exception{OverflowError}
- if there is an invalid numeric constant.
- \end{itemize}
! The \var{symbol} argument means whether to compile it as a statement
! (\code{'single'}, the default) or as an expression (\code{'eval'}).
\strong{Caveat:}
--- 17,36 ----
\begin{funcdesc}{compile_command}
{source\optional{, filename\optional{, symbol}}}
! Tries to compile \var{source}, which should be a string of Python
! code and return a code object if \var{source} is valid
Python code. In that case, the filename attribute of the code object
will be \var{filename}, which defaults to \code{''}.
! Returns \code{None} if \var{source} is \emph{not} valid Python
code, but is a prefix of valid Python code.
! If there is a problem with \var{source}, an exception will be raised.
! \exception{SyntaxError} is raised if there is invalid Python syntax,
! and \exception{OverflowError} if there is an invalid numeric
! constant.
!
! The \var{symbol} argument determines whether \var{source} is compiled
! as a statement (\code{'single'}, the default) or as an expression
! (\code{'eval'}). Any other value will cause \exception{ValueError} to
! be raised.
\strong{Caveat:}
From fdrake@weyr.cnri.reston.va.us Tue Feb 1 18:18:44 2000
From: fdrake@weyr.cnri.reston.va.us (Fred L. Drake)
Date: Tue, 1 Feb 2000 13:18:44 -0500 (EST)
Subject: [Python-checkins] CVS: python/dist/src/Doc/html style.css,1.4.4.1,1.4.4.2
Message-ID: <200002011818.NAA18704@weyr.cnri.reston.va.us>
Update of /projects/cvsroot/python/dist/src/Doc/html
In directory weyr:/home/fdrake/projects/python/Doc-152p1/html
Modified Files:
Tag: release152p1-patches
style.css
Log Message:
Don't name the Courier font; use monospace and let the browser apply
the best available font. Based on a comment by Mauro Cicognini
.
Added a couple of additional style rules for refcount information.
Index: style.css
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Doc/html/style.css,v
retrieving revision 1.4.4.1
retrieving revision 1.4.4.2
diff -C2 -r1.4.4.1 -r1.4.4.2
*** style.css 1999/12/21 15:59:38 1.4.4.1
--- style.css 2000/02/01 18:18:41 1.4.4.2
***************
*** 33,37 ****
h2 { font-size: 150% }
h3, h4 { font-size: 120% }
! code, tt { font-family: courier }
var { font: italic normal serif }
--- 33,37 ----
h2 { font-size: 150% }
h3, h4 { font-size: 120% }
! code, tt { font-family: monospace }
var { font: italic normal serif }
***************
*** 46,49 ****
--- 46,53 ----
.url { font-family: avantgarde, sans-serif }
.file { font-family: avantgarde, sans-serif }
+
+ .refcount-info { font-style: italic }
+ .refcount-info .value { font-weight: bold;
+ color: #006600 }
/*
From fdrake@weyr.cnri.reston.va.us Tue Feb 1 19:06:43 2000
From: fdrake@weyr.cnri.reston.va.us (Fred L. Drake)
Date: Tue, 1 Feb 2000 14:06:43 -0500 (EST)
Subject: [Python-checkins] CVS: python/dist/src/Doc/perl python.perl,1.65.2.2,1.65.2.3
Message-ID: <200002011906.OAA19183@weyr.cnri.reston.va.us>
Update of /projects/cvsroot/python/dist/src/Doc/perl
In directory weyr:/home/fdrake/projects/python/Doc-152p1/perl
Modified Files:
Tag: release152p1-patches
python.perl
Log Message:
Added magic to read from api/refcounts.dat file to generate reference
count information for return values, only for return values of type
PyObject*.
This should take care of *most* questions about reference count
details, but only for the HTML users.
Still needed: explanations of exceptions to the normal refcounting
rules in the descriptive text of the appropriate functions, and
support for non-HTML formats.
Index: python.perl
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Doc/perl/python.perl,v
retrieving revision 1.65.2.2
retrieving revision 1.65.2.3
diff -C2 -r1.65.2.2 -r1.65.2.3
*** python.perl 1999/10/28 18:44:21 1.65.2.2
--- python.perl 2000/02/01 19:06:40 1.65.2.3
***************
*** 559,562 ****
--- 559,595 ----
}
+ $REFCOUNTS_LOADED = 0;
+
+ sub load_refcounts{
+ $REFCOUNTS_LOADED = 1;
+
+ use File::Basename;
+ my $myname, $mydir, $myext;
+ ($myname, $mydir, $myext) = fileparse(__FILE__, '\..*');
+ chop $mydir; # remove trailing '/'
+ ($myname, $mydir, $myext) = fileparse($mydir, '\..*');
+ chop $mydir; # remove trailing '/'
+ $mydir = getcwd() . "$dd$mydir"
+ unless $mydir =~ s|^/|/|;
+ local $_;
+ my $filename = "$mydir${dd}api${dd}refcounts.dat";
+ open(REFCOUNT_FILE, "<$filename") || die "\n$!\n";
+ print "[loading API refcount data]";
+ while () {
+ if (/([a-zA-Z0-9_]+):PyObject\*:([a-zA-Z0-9_]*):(0|[-+]1):(.*)$/) {
+ my($func, $param, $count, $comment) = ($1, $2, $3, $4);
+ #print "\n$func($param) --> $count";
+ $REFCOUNTS{"$func:$param"} = $count;
+ }
+ }
+ }
+
+ sub get_refcount{
+ my ($func, $param) = @_;
+ load_refcounts()
+ unless $REFCOUNTS_LOADED;
+ return $REFCOUNTS{"$func:$param"};
+ }
+
sub do_env_cfuncdesc{
local($_) = @_;
***************
*** 568,572 ****
--- 601,619 ----
$idx =~ s/ \(.*\)//;
$idx =~ s/\(\)//; # ????
+ my $result_rc = get_refcount($function_name, '');
+ my $rcinfo = '';
+ if ($result_rc eq '+1') {
+ $rcinfo = 'Return value:'
+ . "\n New reference.";
+ }
+ elsif ($result_rc eq '0') {
+ $rcinfo = 'Return value:'
+ . "\n Borrowed reference.";
+ }
+ if ($rcinfo ne '') {
+ $rcinfo = "\n
\n $rcinfo\n
";
+ }
return "
$return_type $idx ($arg_list)\n
"
+ . $rcinfo
. $_
. '
';
From fdrake@weyr.cnri.reston.va.us Tue Feb 1 20:12:41 2000
From: fdrake@weyr.cnri.reston.va.us (Fred L. Drake)
Date: Tue, 1 Feb 2000 15:12:41 -0500 (EST)
Subject: [Python-checkins] CVS: python/dist/src/Modules cryptmodule.c,2.5,2.6
Message-ID: <200002012012.PAA19882@weyr.cnri.reston.va.us>
Update of /projects/cvsroot/python/dist/src/Modules
In directory weyr:/home/fdrake/projects/python/Modules
Modified Files:
cryptmodule.c
Log Message:
Added docstring to crypt.crypt() based on the documentation.
Index: cryptmodule.c
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Modules/cryptmodule.c,v
retrieving revision 2.5
retrieving revision 2.6
diff -C2 -r2.5 -r2.6
*** cryptmodule.c 1998/12/04 18:49:42 2.5
--- cryptmodule.c 2000/02/01 20:12:39 2.6
***************
*** 23,28 ****
}
static PyMethodDef crypt_methods[] = {
! {"crypt", crypt_crypt},
{NULL, NULL} /* sentinel */
};
--- 23,37 ----
}
+ static char crypt_crypt__doc__[] = "\
+ crypt(word, salt) -> string\n\
+ word will usually be a user's password. salt is a 2-character string\n\
+ which will be used to select one of 4096 variations of DES. The characters\n\
+ in salt must be either \".\", \"/\", or an alphanumeric character. Returns\n\
+ the hashed password as a string, which will be composed of characters from\n\
+ the same alphabet as the salt.";
+
+
static PyMethodDef crypt_methods[] = {
! {"crypt", crypt_crypt, 0, crypt_crypt__doc__},
{NULL, NULL} /* sentinel */
};
From guido@cnri.reston.va.us Tue Feb 1 23:36:58 2000
From: guido@cnri.reston.va.us (Guido van Rossum)
Date: Tue, 1 Feb 2000 18:36:58 -0500 (EST)
Subject: [Python-checkins] CVS: python/dist/src/Lib urllib.py,1.89,1.90
Message-ID: <200002012336.SAA20090@eric.cnri.reston.va.us>
Update of /projects/cvsroot/python/dist/src/Lib
In directory eric:/projects/python/develop/guido/src/Lib
Modified Files:
urllib.py
Log Message:
Sjoerd Mullender writes:
Fixed a TypeError: not enough arguments; expected 4, got 3.
When authentication is needed, the default http_error_401 method calls
retry_http_basic_auth. The default version of that method expected a
data argument which wasn't provided, so now we provide the argument if
it was given and we also made the data argument optional.
Also changed other calls where data was optional to not pass data if
it was not passed to the calling method (in line with other similar
occurances).
Index: urllib.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/urllib.py,v
retrieving revision 1.89
retrieving revision 1.90
diff -C2 -r1.89 -r1.90
*** urllib.py 1999/12/07 21:37:17 1.89
--- urllib.py 2000/02/01 23:36:55 1.90
***************
*** 500,504 ****
# In case the server sent a relative URL, join with original:
newurl = basejoin("http:" + url, newurl)
! return self.open(newurl, data)
# Error 301 -- also relocated (permanently)
--- 500,507 ----
# In case the server sent a relative URL, join with original:
newurl = basejoin("http:" + url, newurl)
! if data is None:
! return self.open(newurl)
! else:
! return self.open(newurl, data)
# Error 301 -- also relocated (permanently)
***************
*** 518,524 ****
if string.lower(scheme) == 'basic':
name = 'retry_' + self.type + '_basic_auth'
! return getattr(self,name)(url, realm)
! def retry_http_basic_auth(self, url, realm, data):
host, selector = splithost(url)
i = string.find(host, '@') + 1
--- 521,530 ----
if string.lower(scheme) == 'basic':
name = 'retry_' + self.type + '_basic_auth'
! if data is None:
! return getattr(self,name)(url, realm)
! else:
! return getattr(self,name)(url, realm, data)
! def retry_http_basic_auth(self, url, realm, data=None):
host, selector = splithost(url)
i = string.find(host, '@') + 1
***************
*** 528,534 ****
host = user + ':' + passwd + '@' + host
newurl = 'http://' + host + selector
! return self.open(newurl, data)
! def retry_https_basic_auth(self, url, realm):
host, selector = splithost(url)
i = string.find(host, '@') + 1
--- 534,543 ----
host = user + ':' + passwd + '@' + host
newurl = 'http://' + host + selector
! if data is None:
! return self.open(newurl)
! else:
! return self.open(newurl, data)
! def retry_https_basic_auth(self, url, realm, data=None):
host, selector = splithost(url)
i = string.find(host, '@') + 1
Return-Path:
Delivered-To: python-checkins@dinsdale.python.org
Received: from python.org (parrot.python.org [132.151.1.90])
by dinsdale.python.org (Postfix) with ESMTP id 891DA1CD42
for ; Wed, 2 Feb 2000 10:08:59 -0500 (EST)
Received: from cnri.reston.va.us (ns.CNRI.Reston.VA.US [132.151.1.1] (may be forged))
by python.org (8.9.1a/8.9.1) with ESMTP id KAA28495
for ; Wed, 2 Feb 2000 10:08:57 -0500 (EST)
Received: from kaluha.cnri.reston.va.us (kaluha.cnri.reston.va.us [132.151.7.31])
by cnri.reston.va.us (8.9.1a/8.9.1) with ESMTP id KAA12031
for ; Wed, 2 Feb 2000 10:08:58 -0500 (EST)
Received: from eric.cnri.reston.va.us (eric.cnri.reston.va.us [10.27.10.23])
by kaluha.cnri.reston.va.us (8.9.1b+Sun/8.9.1) with ESMTP id KAA05279
for ; Wed, 2 Feb 2000 10:10:22 -0500 (EST)
Received: (from guido@localhost)
by eric.cnri.reston.va.us (8.9.3+Sun/8.9.1) id KAA22017
for python-checkins@python.org; Wed, 2 Feb 2000 10:10:20 -0500 (EST)
Date: Wed, 2 Feb 2000 10:10:20 -0500 (EST)
From: Guido van Rossum
Message-Id: <200002021510.KAA22017@eric.cnri.reston.va.us>
To: python-checkins@python.org
Subject: [Python-checkins] CVS: python/dist/src/Lib fpformat.py,1.5,1.6 copy_reg.py,1.2,1.3 bisect.py,1.3,1.4 audiodev.py,1.7,1.8 UserList.py,1.7,1.8 UserDict.py,1.6,1.7 StringIO.py,1.7,1.8 Queue.py,1.9,1.10 dircmp.py,1.7,1.8 dircache.py,1.4,1.5 cmpcache.py,1.7,1.8 cmp.py,1.7,1.8 cmd.py,1.16,1.17 calendar.py,1.14,1.15 binhex.py,1.10,1.11 bdb.py,1.26,1.27 base64.py,1.8,1.9 aifc.py,1.34,1.35
Sender: python-checkins-admin@python.org
Errors-To: python-checkins-admin@python.org
X-BeenThere: python-checkins@python.org
X-Mailman-Version: 1.2 (experimental)
Precedence: bulk
List-Id: Check-in messages from the Python maintainers
Update of /projects/cvsroot/python/dist/src/Lib
In directory eric:/projects/python/develop/guido/src/Lib
Modified Files:
fpformat.py copy_reg.py bisect.py audiodev.py UserList.py
UserDict.py StringIO.py Queue.py dircmp.py dircache.py
cmpcache.py cmp.py cmd.py calendar.py binhex.py bdb.py
base64.py aifc.py
Log Message:
Mass patch by Ka-Ping Yee:
1. Comments at the beginning of the module, before
functions, and before classes have been turned
into docstrings.
2. Tabs are normalized to four spaces.
Also, removed the "remove" function from dircmp.py, which reimplements
list.remove() (it must have been very old).
Index: fpformat.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/fpformat.py,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -r1.5 -r1.6
*** fpformat.py 1999/09/10 14:34:48 1.5
--- fpformat.py 2000/02/02 15:10:13 1.6
***************
*** 1,14 ****
! # General floating point formatting functions.
! # Functions:
! # fix(x, digits_behind)
! # sci(x, digits_behind)
! # Each takes a number or a string and a number of digits as arguments.
! # Parameters:
! # x: number to be formatted; or a string resembling a number
! # digits_behind: number of digits behind the decimal point
!
import re
--- 1,14 ----
! """General floating point formatting functions.
! Functions:
! fix(x, digits_behind)
! sci(x, digits_behind)
! Each takes a number or a string and a number of digits as arguments.
! Parameters:
! x: number to be formatted; or a string resembling a number
! digits_behind: number of digits behind the decimal point
! """
import re
Index: copy_reg.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/copy_reg.py,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -r1.2 -r1.3
*** copy_reg.py 1997/05/20 18:03:22 1.2
--- copy_reg.py 2000/02/02 15:10:13 1.3
***************
*** 1,3 ****
! # Helper to provide extensibility for pickle/cPickle.
dispatch_table = {}
--- 1,3 ----
! """Helper to provide extensibility for pickle/cPickle."""
dispatch_table = {}
Index: bisect.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/bisect.py,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -r1.3 -r1.4
*** bisect.py 1998/03/26 20:35:09 1.3
--- bisect.py 2000/02/02 15:10:14 1.4
***************
*** 1,25 ****
! # Bisection algorithms
- # Insert item x in list a, and keep it sorted assuming a is sorted
-
def insort(a, x, lo=0, hi=None):
! if hi is None:
! hi = len(a)
! while lo < hi:
! mid = (lo+hi)/2
! if x < a[mid]: hi = mid
! else: lo = mid+1
! a.insert(lo, x)
!
- # Find the index where to insert item x in list a, assuming a is sorted
def bisect(a, x, lo=0, hi=None):
! if hi is None:
! hi = len(a)
! while lo < hi:
! mid = (lo+hi)/2
! if x < a[mid]: hi = mid
! else: lo = mid+1
! return lo
--- 1,23 ----
! """Bisection algorithms."""
def insort(a, x, lo=0, hi=None):
! """Insert item x in list a, and keep it sorted assuming a is sorted."""
! if hi is None:
! hi = len(a)
! while lo < hi:
! mid = (lo+hi)/2
! if x < a[mid]: hi = mid
! else: lo = mid+1
! a.insert(lo, x)
def bisect(a, x, lo=0, hi=None):
! """Find the index where to insert item x in list a, assuming a is sorted."""
! if hi is None:
! hi = len(a)
! while lo < hi:
! mid = (lo+hi)/2
! if x < a[mid]: hi = mid
! else: lo = mid+1
! return lo
Index: audiodev.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/audiodev.py,v
retrieving revision 1.7
retrieving revision 1.8
diff -C2 -r1.7 -r1.8
*** audiodev.py 1999/05/03 18:04:07 1.7
--- audiodev.py 2000/02/02 15:10:14 1.8
***************
*** 1,2 ****
--- 1,4 ----
+ """Classes for manipulating audio devices (currently only for Sun and SGI)"""
+
error = 'audiodev.error'
Index: UserList.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/UserList.py,v
retrieving revision 1.7
retrieving revision 1.8
diff -C2 -r1.7 -r1.8
*** UserList.py 1999/03/26 16:20:18 1.7
--- UserList.py 2000/02/02 15:10:14 1.8
***************
*** 1,3 ****
! # A more or less complete user-defined wrapper around list objects
class UserList:
--- 1,3 ----
! """A more or less complete user-defined wrapper around list objects."""
class UserList:
Index: UserDict.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/UserDict.py,v
retrieving revision 1.6
retrieving revision 1.7
diff -C2 -r1.6 -r1.7
*** UserDict.py 1999/03/26 15:31:12 1.6
--- UserDict.py 2000/02/02 15:10:14 1.7
***************
*** 1,3 ****
! # A more or less complete user-defined wrapper around dictionary objects
class UserDict:
--- 1,3 ----
! """A more or less complete user-defined wrapper around dictionary objects."""
class UserDict:
Index: StringIO.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/StringIO.py,v
retrieving revision 1.7
retrieving revision 1.8
diff -C2 -r1.7 -r1.8
*** StringIO.py 1998/08/18 17:43:08 1.7
--- StringIO.py 2000/02/02 15:10:14 1.8
***************
*** 1,29 ****
! # class StringIO implements file-like objects that read/write a
! # string buffer (a.k.a. "memory files").
! #
! # This implements (nearly) all stdio methods.
! #
! # f = StringIO() # ready for writing
! # f = StringIO(buf) # ready for reading
! # f.close() # explicitly release resources held
! # flag = f.isatty() # always false
! # pos = f.tell() # get current position
! # f.seek(pos) # set current position
! # f.seek(pos, mode) # mode 0: absolute; 1: relative; 2: relative to EOF
! # buf = f.read() # read until EOF
! # buf = f.read(n) # read up to n bytes
! # buf = f.readline() # read until end of line ('\n') or EOF
! # list = f.readlines()# list of f.readline() results until EOF
! # f.write(buf) # write at current position
! # f.writelines(list) # for line in list: f.write(line)
! # f.getvalue() # return whole file's contents as a string
! #
! # Notes:
! # - Using a real file is often faster (but less convenient).
! # - fileno() is left unimplemented so that code which uses it triggers
! # an exception early.
! # - Seeking far beyond EOF and then writing will insert real null
! # bytes that occupy space in the buffer.
! # - There's a simple test set (see end of this file).
import string
--- 1,29 ----
! """File-like objects that read from or write to a string buffer.
!
! This implements (nearly) all stdio methods.
!
! f = StringIO() # ready for writing
! f = StringIO(buf) # ready for reading
! f.close() # explicitly release resources held
! flag = f.isatty() # always false
! pos = f.tell() # get current position
! f.seek(pos) # set current position
! f.seek(pos, mode) # mode 0: absolute; 1: relative; 2: relative to EOF
! buf = f.read() # read until EOF
! buf = f.read(n) # read up to n bytes
! buf = f.readline() # read until end of line ('\n') or EOF
! list = f.readlines()# list of f.readline() results until EOF
! f.write(buf) # write at current position
! f.writelines(list) # for line in list: f.write(line)
! f.getvalue() # return whole file's contents as a string
!
! Notes:
! - Using a real file is often faster (but less convenient).
! - fileno() is left unimplemented so that code which uses it triggers
! an exception early.
! - Seeking far beyond EOF and then writing will insert real null
! bytes that occupy space in the buffer.
! - There's a simple test set (see end of this file).
! """
import string
Index: Queue.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/Queue.py,v
retrieving revision 1.9
retrieving revision 1.10
diff -C2 -r1.9 -r1.10
*** Queue.py 1999/09/09 14:54:28 1.9
--- Queue.py 2000/02/02 15:10:14 1.10
***************
*** 1,3 ****
! # A multi-producer, multi-consumer queue.
# define this exception to be compatible with Python 1.5's class
--- 1,3 ----
! """A multi-producer, multi-consumer queue."""
# define this exception to be compatible with Python 1.5's class
Index: dircmp.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/dircmp.py,v
retrieving revision 1.7
retrieving revision 1.8
diff -C2 -r1.7 -r1.8
*** dircmp.py 1992/12/14 12:57:38 1.7
--- dircmp.py 2000/02/02 15:10:14 1.8
***************
*** 1,5 ****
! # Module 'dirmp'
! #
! # Defines a class to build directory diff tools on.
import os
--- 1,3 ----
! """A class to build directory diff tools on."""
import os
***************
*** 10,203 ****
from stat import *
- # Directory comparison class.
- #
class dircmp:
! #
! def new(self, a, b): # Initialize
! self.a = a
! self.b = b
! # Properties that caller may change before calling self.run():
! self.hide = [os.curdir, os.pardir] # Names never to be shown
! self.ignore = ['RCS', 'tags'] # Names ignored in comparison
! #
! return self
! #
! def run(self): # Compare everything except common subdirectories
! self.a_list = filter(dircache.listdir(self.a), self.hide)
! self.b_list = filter(dircache.listdir(self.b), self.hide)
! self.a_list.sort()
! self.b_list.sort()
! self.phase1()
! self.phase2()
! self.phase3()
! #
! def phase1(self): # Compute common names
! self.a_only = []
! self.common = []
! for x in self.a_list:
! if x in self.b_list:
! self.common.append(x)
! else:
! self.a_only.append(x)
! #
! self.b_only = []
! for x in self.b_list:
! if x not in self.common:
! self.b_only.append(x)
! #
! def phase2(self): # Distinguish files, directories, funnies
! self.common_dirs = []
! self.common_files = []
! self.common_funny = []
! #
! for x in self.common:
! a_path = os.path.join(self.a, x)
! b_path = os.path.join(self.b, x)
! #
! ok = 1
! try:
! a_stat = statcache.stat(a_path)
! except os.error, why:
! # print 'Can\'t stat', a_path, ':', why[1]
! ok = 0
! try:
! b_stat = statcache.stat(b_path)
! except os.error, why:
! # print 'Can\'t stat', b_path, ':', why[1]
! ok = 0
! #
! if ok:
! a_type = S_IFMT(a_stat[ST_MODE])
! b_type = S_IFMT(b_stat[ST_MODE])
! if a_type <> b_type:
! self.common_funny.append(x)
! elif S_ISDIR(a_type):
! self.common_dirs.append(x)
! elif S_ISREG(a_type):
! self.common_files.append(x)
! else:
! self.common_funny.append(x)
! else:
! self.common_funny.append(x)
! #
! def phase3(self): # Find out differences between common files
! xx = cmpfiles(self.a, self.b, self.common_files)
! self.same_files, self.diff_files, self.funny_files = xx
! #
! def phase4(self): # Find out differences between common subdirectories
! # A new dircmp object is created for each common subdirectory,
! # these are stored in a dictionary indexed by filename.
! # The hide and ignore properties are inherited from the parent
! self.subdirs = {}
! for x in self.common_dirs:
! a_x = os.path.join(self.a, x)
! b_x = os.path.join(self.b, x)
! self.subdirs[x] = newdd = dircmp().new(a_x, b_x)
! newdd.hide = self.hide
! newdd.ignore = self.ignore
! newdd.run()
! #
! def phase4_closure(self): # Recursively call phase4() on subdirectories
! self.phase4()
! for x in self.subdirs.keys():
! self.subdirs[x].phase4_closure()
! #
! def report(self): # Print a report on the differences between a and b
! # Assume that phases 1 to 3 have been executed
! # Output format is purposely lousy
! print 'diff', self.a, self.b
! if self.a_only:
! print 'Only in', self.a, ':', self.a_only
! if self.b_only:
! print 'Only in', self.b, ':', self.b_only
! if self.same_files:
! print 'Identical files :', self.same_files
! if self.diff_files:
! print 'Differing files :', self.diff_files
! if self.funny_files:
! print 'Trouble with common files :', self.funny_files
! if self.common_dirs:
! print 'Common subdirectories :', self.common_dirs
! if self.common_funny:
! print 'Common funny cases :', self.common_funny
! #
! def report_closure(self): # Print reports on self and on subdirs
! # If phase 4 hasn't been done, no subdir reports are printed
! self.report()
! try:
! x = self.subdirs
! except AttributeError:
! return # No subdirectories computed
! for x in self.subdirs.keys():
! print
! self.subdirs[x].report_closure()
! #
! def report_phase4_closure(self): # Report and do phase 4 recursively
! self.report()
! self.phase4()
! for x in self.subdirs.keys():
! print
! self.subdirs[x].report_phase4_closure()
!
!
! # Compare common files in two directories.
! # Return:
! # - files that compare equal
! # - files that compare different
! # - funny cases (can't stat etc.)
! #
def cmpfiles(a, b, common):
! res = ([], [], [])
! for x in common:
! res[cmp(os.path.join(a, x), os.path.join(b, x))].append(x)
! return res
- # Compare two files.
- # Return:
- # 0 for equal
- # 1 for different
- # 2 for funny cases (can't stat, etc.)
- #
def cmp(a, b):
! try:
! if cmpcache.cmp(a, b): return 0
! return 1
! except os.error:
! return 2
!
!
! # Remove a list item.
! # NB: This modifies the list argument.
! #
! def remove(list, item):
! for i in range(len(list)):
! if list[i] == item:
! del list[i]
! break
- # Return a copy with items that occur in skip removed.
- #
def filter(list, skip):
! result = []
! for item in list:
! if item not in skip: result.append(item)
! return result
! # Demonstration and testing.
! #
def demo():
! import sys
! import getopt
! options, args = getopt.getopt(sys.argv[1:], 'r')
! if len(args) <> 2: raise getopt.error, 'need exactly two args'
! dd = dircmp().new(args[0], args[1])
! dd.run()
! if ('-r', '') in options:
! dd.report_phase4_closure()
! else:
! dd.report()
! # demo()
--- 8,201 ----
from stat import *
class dircmp:
! """Directory comparison class."""
!
! def new(self, a, b):
! """Initialize."""
! self.a = a
! self.b = b
! # Properties that caller may change before calling self.run():
! self.hide = [os.curdir, os.pardir] # Names never to be shown
! self.ignore = ['RCS', 'tags'] # Names ignored in comparison
!
! return self
!
! def run(self):
! """Compare everything except common subdirectories."""
! self.a_list = filter(dircache.listdir(self.a), self.hide)
! self.b_list = filter(dircache.listdir(self.b), self.hide)
! self.a_list.sort()
! self.b_list.sort()
! self.phase1()
! self.phase2()
! self.phase3()
!
! def phase1(self):
! """Compute common names."""
! self.a_only = []
! self.common = []
! for x in self.a_list:
! if x in self.b_list:
! self.common.append(x)
! else:
! self.a_only.append(x)
!
! self.b_only = []
! for x in self.b_list:
! if x not in self.common:
! self.b_only.append(x)
!
! def phase2(self):
! """Distinguish files, directories, funnies."""
! self.common_dirs = []
! self.common_files = []
! self.common_funny = []
!
! for x in self.common:
! a_path = os.path.join(self.a, x)
! b_path = os.path.join(self.b, x)
!
! ok = 1
! try:
! a_stat = statcache.stat(a_path)
! except os.error, why:
! # print 'Can\'t stat', a_path, ':', why[1]
! ok = 0
! try:
! b_stat = statcache.stat(b_path)
! except os.error, why:
! # print 'Can\'t stat', b_path, ':', why[1]
! ok = 0
!
! if ok:
! a_type = S_IFMT(a_stat[ST_MODE])
! b_type = S_IFMT(b_stat[ST_MODE])
! if a_type <> b_type:
! self.common_funny.append(x)
! elif S_ISDIR(a_type):
! self.common_dirs.append(x)
! elif S_ISREG(a_type):
! self.common_files.append(x)
! else:
! self.common_funny.append(x)
! else:
! self.common_funny.append(x)
!
! def phase3(self):
! """Find out differences between common files."""
! xx = cmpfiles(self.a, self.b, self.common_files)
! self.same_files, self.diff_files, self.funny_files = xx
!
! def phase4(self):
! """Find out differences between common subdirectories.
! A new dircmp object is created for each common subdirectory,
! these are stored in a dictionary indexed by filename.
! The hide and ignore properties are inherited from the parent."""
! self.subdirs = {}
! for x in self.common_dirs:
! a_x = os.path.join(self.a, x)
! b_x = os.path.join(self.b, x)
! self.subdirs[x] = newdd = dircmp().new(a_x, b_x)
! newdd.hide = self.hide
! newdd.ignore = self.ignore
! newdd.run()
!
! def phase4_closure(self):
! """Recursively call phase4() on subdirectories."""
! self.phase4()
! for x in self.subdirs.keys():
! self.subdirs[x].phase4_closure()
!
! def report(self):
! """Print a report on the differences between a and b."""
! # Assume that phases 1 to 3 have been executed
! # Output format is purposely lousy
! print 'diff', self.a, self.b
! if self.a_only:
! print 'Only in', self.a, ':', self.a_only
! if self.b_only:
! print 'Only in', self.b, ':', self.b_only
! if self.same_files:
! print 'Identical files :', self.same_files
! if self.diff_files:
! print 'Differing files :', self.diff_files
! if self.funny_files:
! print 'Trouble with common files :', self.funny_files
! if self.common_dirs:
! print 'Common subdirectories :', self.common_dirs
! if self.common_funny:
! print 'Common funny cases :', self.common_funny
!
! def report_closure(self):
! """Print reports on self and on subdirs.
! If phase 4 hasn't been done, no subdir reports are printed."""
! self.report()
! try:
! x = self.subdirs
! except AttributeError:
! return # No subdirectories computed
! for x in self.subdirs.keys():
! print
! self.subdirs[x].report_closure()
!
! def report_phase4_closure(self):
! """Report and do phase 4 recursively."""
! self.report()
! self.phase4()
! for x in self.subdirs.keys():
! print
! self.subdirs[x].report_phase4_closure()
!
!
def cmpfiles(a, b, common):
! """Compare common files in two directories.
! Return:
! - files that compare equal
! - files that compare different
! - funny cases (can't stat etc.)"""
!
! res = ([], [], [])
! for x in common:
! res[cmp(os.path.join(a, x), os.path.join(b, x))].append(x)
! return res
def cmp(a, b):
! """Compare two files.
! Return:
! 0 for equal
! 1 for different
! 2 for funny cases (can't stat, etc.)"""
!
! try:
! if cmpcache.cmp(a, b): return 0
! return 1
! except os.error:
! return 2
def filter(list, skip):
! """Return a copy with items that occur in skip removed."""
+ result = []
+ for item in list:
+ if item not in skip: result.append(item)
+ return result
!
def demo():
! """Demonstration and testing."""
!
! import sys
! import getopt
! options, args = getopt.getopt(sys.argv[1:], 'r')
! if len(args) <> 2: raise getopt.error, 'need exactly two args'
! dd = dircmp().new(args[0], args[1])
! dd.run()
! if ('-r', '') in options:
! dd.report_phase4_closure()
! else:
! dd.report()
! if __name__ == "__main__":
! demo()
Index: dircache.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/dircache.py,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -r1.4 -r1.5
*** dircache.py 1992/03/31 18:55:14 1.4
--- dircache.py 2000/02/02 15:10:14 1.5
***************
*** 1,7 ****
! # Module 'dircache'
! #
! # Return a sorted list of the files in a directory, using a cache
! # to avoid reading the directory more often than necessary.
! # Also contains a subroutine to append slashes to directories.
import os
--- 1,5 ----
! """Return a sorted list of the files in a directory, using a cache
! to avoid reading the directory more often than necessary.
! Also contains a subroutine to append slashes to directories."""
import os
***************
*** 9,35 ****
cache = {}
! def listdir(path): # List directory contents, using cache
! try:
! cached_mtime, list = cache[path]
! del cache[path]
! except KeyError:
! cached_mtime, list = -1, []
! try:
! mtime = os.stat(path)[8]
! except os.error:
! return []
! if mtime <> cached_mtime:
! try:
! list = os.listdir(path)
! except os.error:
! return []
! list.sort()
! cache[path] = mtime, list
! return list
opendir = listdir # XXX backward compatibility
! def annotate(head, list): # Add '/' suffixes to directories
! for i in range(len(list)):
! if os.path.isdir(os.path.join(head, list[i])):
! list[i] = list[i] + '/'
--- 7,35 ----
cache = {}
! def listdir(path):
! """List directory contents, using cache."""
! try:
! cached_mtime, list = cache[path]
! del cache[path]
! except KeyError:
! cached_mtime, list = -1, []
! try:
! mtime = os.stat(path)[8]
! except os.error:
! return []
! if mtime <> cached_mtime:
! try:
! list = os.listdir(path)
! except os.error:
! return []
! list.sort()
! cache[path] = mtime, list
! return list
opendir = listdir # XXX backward compatibility
! def annotate(head, list):
! """Add '/' suffixes to directories."""
! for i in range(len(list)):
! if os.path.isdir(os.path.join(head, list[i])):
! list[i] = list[i] + '/'
Index: cmpcache.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/cmpcache.py,v
retrieving revision 1.7
retrieving revision 1.8
diff -C2 -r1.7 -r1.8
*** cmpcache.py 1999/06/25 14:21:44 1.7
--- cmpcache.py 2000/02/02 15:10:14 1.8
***************
*** 1,12 ****
! # Module 'cmpcache'
! #
! # Efficiently compare files, boolean outcome only (equal / not equal).
! #
! # Tricks (used in this order):
! # - Use the statcache module to avoid statting files more than once
! # - Files with identical type, size & mtime are assumed to be clones
! # - Files with different type or size cannot be identical
! # - We keep a cache of outcomes of earlier comparisons
! # - We don't fork a process to run 'cmp' but read the files ourselves
import os
--- 1,11 ----
! """Efficiently compare files, boolean outcome only (equal / not equal).
!
! Tricks (used in this order):
! - Use the statcache module to avoid statting files more than once
! - Files with identical type, size & mtime are assumed to be clones
! - Files with different type or size cannot be identical
! - We keep a cache of outcomes of earlier comparisons
! - We don't fork a process to run 'cmp' but read the files ourselves
! """
import os
***************
*** 20,68 ****
- # Compare two files, use the cache if possible.
- # May raise os.error if a stat or open of either fails.
- #
def cmp(f1, f2, shallow=1):
! # Return 1 for identical files, 0 for different.
! # Raise exceptions if either file could not be statted, read, etc.
! s1, s2 = sig(statcache.stat(f1)), sig(statcache.stat(f2))
! if not S_ISREG(s1[0]) or not S_ISREG(s2[0]):
! # Either is a not a plain file -- always report as different
! return 0
! if shallow and s1 == s2:
! # type, size & mtime match -- report same
! return 1
! if s1[:2] <> s2[:2]: # Types or sizes differ, don't bother
! # types or sizes differ -- report different
! return 0
! # same type and size -- look in the cache
! key = f1 + ' ' + f2
! if cache.has_key(key):
! cs1, cs2, outcome = cache[key]
! # cache hit
! if s1 == cs1 and s2 == cs2:
! # cached signatures match
! return outcome
! # stale cached signature(s)
! # really compare
! outcome = do_cmp(f1, f2)
! cache[key] = s1, s2, outcome
! return outcome
- # Return signature (i.e., type, size, mtime) from raw stat data.
- #
def sig(st):
! return S_IFMT(st[ST_MODE]), st[ST_SIZE], st[ST_MTIME]
- # Compare two files, really.
- #
def do_cmp(f1, f2):
! #print ' cmp', f1, f2 # XXX remove when debugged
! bufsize = 8*1024 # Could be tuned
! fp1 = open(f1, 'rb')
! fp2 = open(f2, 'rb')
! while 1:
! b1 = fp1.read(bufsize)
! b2 = fp2.read(bufsize)
! if b1 <> b2: return 0
! if not b1: return 1
--- 19,64 ----
def cmp(f1, f2, shallow=1):
! """Compare two files, use the cache if possible.
! May raise os.error if a stat or open of either fails.
! Return 1 for identical files, 0 for different.
! Raise exceptions if either file could not be statted, read, etc."""
! s1, s2 = sig(statcache.stat(f1)), sig(statcache.stat(f2))
! if not S_ISREG(s1[0]) or not S_ISREG(s2[0]):
! # Either is a not a plain file -- always report as different
! return 0
! if shallow and s1 == s2:
! # type, size & mtime match -- report same
! return 1
! if s1[:2] <> s2[:2]: # Types or sizes differ, don't bother
! # types or sizes differ -- report different
! return 0
! # same type and size -- look in the cache
! key = f1 + ' ' + f2
! if cache.has_key(key):
! cs1, cs2, outcome = cache[key]
! # cache hit
! if s1 == cs1 and s2 == cs2:
! # cached signatures match
! return outcome
! # stale cached signature(s)
! # really compare
! outcome = do_cmp(f1, f2)
! cache[key] = s1, s2, outcome
! return outcome
def sig(st):
! """Return signature (i.e., type, size, mtime) from raw stat data."""
! return S_IFMT(st[ST_MODE]), st[ST_SIZE], st[ST_MTIME]
def do_cmp(f1, f2):
! """Compare two files, really."""
! #print ' cmp', f1, f2 # XXX remove when debugged
! bufsize = 8*1024 # Could be tuned
! fp1 = open(f1, 'rb')
! fp2 = open(f2, 'rb')
! while 1:
! b1 = fp1.read(bufsize)
! b2 = fp2.read(bufsize)
! if b1 <> b2: return 0
! if not b1: return 1
Index: cmp.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/cmp.py,v
retrieving revision 1.7
retrieving revision 1.8
diff -C2 -r1.7 -r1.8
*** cmp.py 1999/06/25 14:12:50 1.7
--- cmp.py 2000/02/02 15:10:14 1.8
***************
*** 1,61 ****
! # Module 'cmp'
! # Efficiently compare files, boolean outcome only (equal / not equal).
- # Tricks (used in this order):
- # - Files with identical type, size & mtime are assumed to be clones
- # - Files with different type or size cannot be identical
- # - We keep a cache of outcomes of earlier comparisons
- # - We don't fork a process to run 'cmp' but read the files ourselves
-
import os
cache = {}
! def cmp(f1, f2, shallow=1): # Compare two files, use the cache if possible.
! # Return 1 for identical files, 0 for different.
! # Raise exceptions if either file could not be statted, read, etc.
! s1, s2 = sig(os.stat(f1)), sig(os.stat(f2))
! if s1[0] <> 8 or s2[0] <> 8:
! # Either is a not a plain file -- always report as different
! return 0
! if shallow and s1 == s2:
! # type, size & mtime match -- report same
! return 1
! if s1[:2] <> s2[:2]: # Types or sizes differ, don't bother
! # types or sizes differ -- report different
! return 0
! # same type and size -- look in the cache
! key = (f1, f2)
! try:
! cs1, cs2, outcome = cache[key]
! # cache hit
! if s1 == cs1 and s2 == cs2:
! # cached signatures match
! return outcome
! # stale cached signature(s)
! except KeyError:
! # cache miss
! pass
! # really compare
! outcome = do_cmp(f1, f2)
! cache[key] = s1, s2, outcome
! return outcome
!
! def sig(st): # Return signature (i.e., type, size, mtime) from raw stat data
! # 0-5: st_mode, st_ino, st_dev, st_nlink, st_uid, st_gid
! # 6-9: st_size, st_atime, st_mtime, st_ctime
! type = st[0] / 4096
! size = st[6]
! mtime = st[8]
! return type, size, mtime
!
! def do_cmp(f1, f2): # Compare two files, really
! bufsize = 8*1024 # Could be tuned
! fp1 = open(f1, 'rb')
! fp2 = open(f2, 'rb')
! while 1:
! b1 = fp1.read(bufsize)
! b2 = fp2.read(bufsize)
! if b1 <> b2: return 0
! if not b1: return 1
--- 1,63 ----
! """Efficiently compare files, boolean outcome only (equal / not equal).
! Tricks (used in this order):
! - Files with identical type, size & mtime are assumed to be clones
! - Files with different type or size cannot be identical
! - We keep a cache of outcomes of earlier comparisons
! - We don't fork a process to run 'cmp' but read the files ourselves
! """
import os
cache = {}
! def cmp(f1, f2, shallow=1):
! """Compare two files, use the cache if possible.
! Return 1 for identical files, 0 for different.
! Raise exceptions if either file could not be statted, read, etc."""
! s1, s2 = sig(os.stat(f1)), sig(os.stat(f2))
! if s1[0] <> 8 or s2[0] <> 8:
! # Either is a not a plain file -- always report as different
! return 0
! if shallow and s1 == s2:
! # type, size & mtime match -- report same
! return 1
! if s1[:2] <> s2[:2]: # Types or sizes differ, don't bother
! # types or sizes differ -- report different
! return 0
! # same type and size -- look in the cache
! key = (f1, f2)
! try:
! cs1, cs2, outcome = cache[key]
! # cache hit
! if s1 == cs1 and s2 == cs2:
! # cached signatures match
! return outcome
! # stale cached signature(s)
! except KeyError:
! # cache miss
! pass
! # really compare
! outcome = do_cmp(f1, f2)
! cache[key] = s1, s2, outcome
! return outcome
!
! def sig(st):
! """Return signature (i.e., type, size, mtime) from raw stat data
! 0-5: st_mode, st_ino, st_dev, st_nlink, st_uid, st_gid
! 6-9: st_size, st_atime, st_mtime, st_ctime"""
! type = st[0] / 4096
! size = st[6]
! mtime = st[8]
! return type, size, mtime
!
! def do_cmp(f1, f2):
! """Compare two files, really."""
! bufsize = 8*1024 # Could be tuned
! fp1 = open(f1, 'rb')
! fp2 = open(f2, 'rb')
! while 1:
! b1 = fp1.read(bufsize)
! b2 = fp2.read(bufsize)
! if b1 <> b2: return 0
! if not b1: return 1
Index: cmd.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/cmd.py,v
retrieving revision 1.16
retrieving revision 1.17
diff -C2 -r1.16 -r1.17
*** cmd.py 1999/05/03 18:08:16 1.16
--- cmd.py 2000/02/02 15:10:14 1.17
***************
*** 1,39 ****
! # A generic class to build line-oriented command interpreters
! #
! # Interpreters constructed with this class obey the following conventions:
! #
! # 1. End of file on input is processed as the command 'EOF'.
! # 2. A command is parsed out of each line by collecting the prefix composed
! # of characters in the identchars member.
! # 3. A command `foo' is dispatched to a method 'do_foo()'; the do_ method
! # is passed a single argument consisting of the remainder of the line.
! # 4. Typing an empty line repeats the last command. (Actually, it calls the
! # method `emptyline', which may be overridden in a subclass.)
! # 5. There is a predefined `help' method. Given an argument `topic', it
! # calls the command `help_topic'. With no arguments, it lists all topics
! # with defined help_ functions, broken into up to three topics; documented
! # commands, miscellaneous help topics, and undocumented commands.
! # 6. The command '?' is a synonym for `help'. The command '!' is a synonym
! # for `shell', if a do_shell method exists.
! #
! # The `default' method may be overridden to intercept commands for which there
! # is no do_ method.
! #
! # The data member `self.ruler' sets the character used to draw separator lines
! # in the help messages. If empty, no ruler line is drawn. It defaults to "=".
! #
! # If the value of `self.intro' is nonempty when the cmdloop method is called,
! # it is printed out on interpreter startup. This value may be overridden
! # via an optional argument to the cmdloop() method.
! #
! # The data members `self.doc_header', `self.misc_header', and
! # `self.undoc_header' set the headers used for the help function's
! # listings of documented functions, miscellaneous topics, and undocumented
! # functions respectively.
! #
! # These interpreters use raw_input; thus, if the readline module is loaded,
! # they automatically support Emacs-like command history and editing features.
! #
import string
--- 1,39 ----
! """A generic class to build line-oriented command interpreters.
+ Interpreters constructed with this class obey the following conventions:
+
+ 1. End of file on input is processed as the command 'EOF'.
+ 2. A command is parsed out of each line by collecting the prefix composed
+ of characters in the identchars member.
+ 3. A command `foo' is dispatched to a method 'do_foo()'; the do_ method
+ is passed a single argument consisting of the remainder of the line.
+ 4. Typing an empty line repeats the last command. (Actually, it calls the
+ method `emptyline', which may be overridden in a subclass.)
+ 5. There is a predefined `help' method. Given an argument `topic', it
+ calls the command `help_topic'. With no arguments, it lists all topics
+ with defined help_ functions, broken into up to three topics; documented
+ commands, miscellaneous help topics, and undocumented commands.
+ 6. The command '?' is a synonym for `help'. The command '!' is a synonym
+ for `shell', if a do_shell method exists.
+
+ The `default' method may be overridden to intercept commands for which there
+ is no do_ method.
+
+ The data member `self.ruler' sets the character used to draw separator lines
+ in the help messages. If empty, no ruler line is drawn. It defaults to "=".
+
+ If the value of `self.intro' is nonempty when the cmdloop method is called,
+ it is printed out on interpreter startup. This value may be overridden
+ via an optional argument to the cmdloop() method.
+
+ The data members `self.doc_header', `self.misc_header', and
+ `self.undoc_header' set the headers used for the help function's
+ listings of documented functions, miscellaneous topics, and undocumented
+ functions respectively.
+
+ These interpreters use raw_input; thus, if the readline module is loaded,
+ they automatically support Emacs-like command history and editing features.
+ """
+
import string
***************
*** 42,187 ****
class Cmd:
! prompt = PROMPT
! identchars = IDENTCHARS
! ruler = '='
! lastcmd = ''
! cmdqueue = []
! intro = None
! doc_leader = ""
! doc_header = "Documented commands (type help ):"
! misc_header = "Miscellaneous help topics:"
! undoc_header = "Undocumented commands:"
! nohelp = "*** No help on %s"
!
! def __init__(self): pass
!
! def cmdloop(self, intro=None):
! self.preloop()
! if intro != None:
! self.intro = intro
! if self.intro:
! print self.intro
! stop = None
! while not stop:
! if self.cmdqueue:
! line = self.cmdqueue[0]
! del self.cmdqueue[0]
! else:
! try:
! line = raw_input(self.prompt)
! except EOFError:
! line = 'EOF'
! line = self.precmd(line)
! stop = self.onecmd(line)
! stop = self.postcmd(stop, line)
! self.postloop()
!
! def precmd(self, line):
! return line
!
! def postcmd(self, stop, line):
! return stop
!
! def preloop(self):
! pass
!
! def postloop(self):
! pass
!
! def onecmd(self, line):
! line = string.strip(line)
! if line == '?':
! line = 'help'
! elif line == '!':
! if hasattr(self, 'do_shell'):
! line = 'shell'
! else:
! return self.default(line)
! elif not line:
! return self.emptyline()
! self.lastcmd = line
! i, n = 0, len(line)
! while i < n and line[i] in self.identchars: i = i+1
! cmd, arg = line[:i], string.strip(line[i:])
! if cmd == '':
! return self.default(line)
! else:
! try:
! func = getattr(self, 'do_' + cmd)
! except AttributeError:
! return self.default(line)
! return func(arg)
!
! def emptyline(self):
! if self.lastcmd:
! return self.onecmd(self.lastcmd)
!
! def default(self, line):
! print '*** Unknown syntax:', line
!
! def do_help(self, arg):
! if arg:
! # XXX check arg syntax
! try:
! func = getattr(self, 'help_' + arg)
! except:
! try:
! doc=getattr(self, 'do_' + arg).__doc__
! if doc:
! print doc
! return
! except:
! pass
! print self.nohelp % (arg,)
! return
! func()
! else:
! # Inheritance says we have to look in class and
! # base classes; order is not important.
! names = []
! classes = [self.__class__]
! while classes:
! aclass = classes[0]
! if aclass.__bases__:
! classes = classes + list(aclass.__bases__)
! names = names + dir(aclass)
! del classes[0]
! cmds_doc = []
! cmds_undoc = []
! help = {}
! for name in names:
! if name[:5] == 'help_':
! help[name[5:]]=1
! names.sort()
! # There can be duplicates if routines overridden
! prevname = ''
! for name in names:
! if name[:3] == 'do_':
! if name == prevname:
! continue
! prevname = name
! cmd=name[3:]
! if help.has_key(cmd):
! cmds_doc.append(cmd)
! del help[cmd]
! elif getattr(self, name).__doc__:
! cmds_doc.append(cmd)
! else:
! cmds_undoc.append(cmd)
! print self.doc_leader
! self.print_topics(self.doc_header, cmds_doc, 15,80)
! self.print_topics(self.misc_header, help.keys(),15,80)
! self.print_topics(self.undoc_header, cmds_undoc, 15,80)
!
! def print_topics(self, header, cmds, cmdlen, maxcol):
! if cmds:
! print header;
! if self.ruler:
! print self.ruler * len(header)
! (cmds_per_line,junk)=divmod(maxcol,cmdlen)
! col=cmds_per_line
! for cmd in cmds:
! if col==0: print
! print (("%-"+`cmdlen`+"s") % cmd),
! col = (col+1) % cmds_per_line
! print "\n"
--- 42,187 ----
class Cmd:
! prompt = PROMPT
! identchars = IDENTCHARS
! ruler = '='
! lastcmd = ''
! cmdqueue = []
! intro = None
! doc_leader = ""
! doc_header = "Documented commands (type help ):"
! misc_header = "Miscellaneous help topics:"
! undoc_header = "Undocumented commands:"
! nohelp = "*** No help on %s"
!
! def __init__(self): pass
!
! def cmdloop(self, intro=None):
! self.preloop()
! if intro != None:
! self.intro = intro
! if self.intro:
! print self.intro
! stop = None
! while not stop:
! if self.cmdqueue:
! line = self.cmdqueue[0]
! del self.cmdqueue[0]
! else:
! try:
! line = raw_input(self.prompt)
! except EOFError:
! line = 'EOF'
! line = self.precmd(line)
! stop = self.onecmd(line)
! stop = self.postcmd(stop, line)
! self.postloop()
!
! def precmd(self, line):
! return line
!
! def postcmd(self, stop, line):
! return stop
!
! def preloop(self):
! pass
!
! def postloop(self):
! pass
!
! def onecmd(self, line):
! line = string.strip(line)
! if line == '?':
! line = 'help'
! elif line == '!':
! if hasattr(self, 'do_shell'):
! line = 'shell'
! else:
! return self.default(line)
! elif not line:
! return self.emptyline()
! self.lastcmd = line
! i, n = 0, len(line)
! while i < n and line[i] in self.identchars: i = i+1
! cmd, arg = line[:i], string.strip(line[i:])
! if cmd == '':
! return self.default(line)
! else:
! try:
! func = getattr(self, 'do_' + cmd)
! except AttributeError:
! return self.default(line)
! return func(arg)
!
! def emptyline(self):
! if self.lastcmd:
! return self.onecmd(self.lastcmd)
!
! def default(self, line):
! print '*** Unknown syntax:', line
!
! def do_help(self, arg):
! if arg:
! # XXX check arg syntax
! try:
! func = getattr(self, 'help_' + arg)
! except:
! try:
! doc=getattr(self, 'do_' + arg).__doc__
! if doc:
! print doc
! return
! except:
! pass
! print self.nohelp % (arg,)
! return
! func()
! else:
! # Inheritance says we have to look in class and
! # base classes; order is not important.
! names = []
! classes = [self.__class__]
! while classes:
! aclass = classes[0]
! if aclass.__bases__:
! classes = classes + list(aclass.__bases__)
! names = names + dir(aclass)
! del classes[0]
! cmds_doc = []
! cmds_undoc = []
! help = {}
! for name in names:
! if name[:5] == 'help_':
! help[name[5:]]=1
! names.sort()
! # There can be duplicates if routines overridden
! prevname = ''
! for name in names:
! if name[:3] == 'do_':
! if name == prevname:
! continue
! prevname = name
! cmd=name[3:]
! if help.has_key(cmd):
! cmds_doc.append(cmd)
! del help[cmd]
! elif getattr(self, name).__doc__:
! cmds_doc.append(cmd)
! else:
! cmds_undoc.append(cmd)
! print self.doc_leader
! self.print_topics(self.doc_header, cmds_doc, 15,80)
! self.print_topics(self.misc_header, help.keys(),15,80)
! self.print_topics(self.undoc_header, cmds_undoc, 15,80)
!
! def print_topics(self, header, cmds, cmdlen, maxcol):
! if cmds:
! print header;
! if self.ruler:
! print self.ruler * len(header)
! (cmds_per_line,junk)=divmod(maxcol,cmdlen)
! col=cmds_per_line
! for cmd in cmds:
! if col==0: print
! print (("%-"+`cmdlen`+"s") % cmd),
! col = (col+1) % cmds_per_line
! print "\n"
Index: calendar.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/calendar.py,v
retrieving revision 1.14
retrieving revision 1.15
diff -C2 -r1.14 -r1.15
*** calendar.py 1999/06/09 15:07:38 1.14
--- calendar.py 2000/02/02 15:10:14 1.15
***************
*** 1,5 ****
! ###############################
! # Calendar printing functions #
! ###############################
# Revision 2: uses funtions from built-in time module
--- 1,3 ----
! """Calendar printing functions"""
# Revision 2: uses funtions from built-in time module
***************
*** 23,170 ****
# Full and abbreviated names of weekdays
! day_name = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', \
! 'Friday', 'Saturday', 'Sunday']
day_abbr = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
# Full and abbreviated names of months (1-based arrays!!!)
! month_name = ['', 'January', 'February', 'March', 'April', \
! 'May', 'June', 'July', 'August', \
! 'September', 'October', 'November', 'December']
! month_abbr = [' ', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', \
! 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
- # Return 1 for leap years, 0 for non-leap years
def isleap(year):
! return year % 4 == 0 and (year % 100 <> 0 or year % 400 == 0)
- # Return number of leap years in range [y1, y2)
- # Assume y1 <= y2 and no funny (non-leap century) years
def leapdays(y1, y2):
! return (y2+3)/4 - (y1+3)/4
- # Return weekday (0-6 ~ Mon-Sun) for year (1970-...), month (1-12), day (1-31)
def weekday(year, month, day):
! secs = mktime((year, month, day, 0, 0, 0, 0, 0, 0))
! tuple = localtime(secs)
! return tuple[6]
- # Return weekday (0-6 ~ Mon-Sun) and number of days (28-31) for year, month
def monthrange(year, month):
! if not 1 <= month <= 12: raise ValueError, 'bad month number'
! day1 = weekday(year, month, 1)
! ndays = mdays[month] + (month == February and isleap(year))
! return day1, ndays
- # Return a matrix representing a month's calendar
- # Each row represents a week; days outside this month are zero
def _monthcalendar(year, month):
! day1, ndays = monthrange(year, month)
! rows = []
! r7 = range(7)
! day = 1 - day1
! while day <= ndays:
! row = [0, 0, 0, 0, 0, 0, 0]
! for i in r7:
! if 1 <= day <= ndays: row[i] = day
! day = day + 1
! rows.append(row)
! return rows
- # Caching interface to _monthcalendar
_mc_cache = {}
def monthcalendar(year, month):
! key = (year, month)
! if _mc_cache.has_key(key):
! return _mc_cache[key]
! else:
! _mc_cache[key] = ret = _monthcalendar(year, month)
! return ret
- # Center a string in a field
def _center(str, width):
! n = width - len(str)
! if n <= 0: return str
! return ' '*((n+1)/2) + str + ' '*((n)/2)
# XXX The following code knows that print separates items with space!
- # Print a single week (no newline)
def prweek(week, width):
! for day in week:
! if day == 0: s = ''
! else: s = `day`
! print _center(s, width),
- # Return a header for a week
def weekheader(width):
! str = ''
! if width >= 9: names = day_name
! else: names = day_abbr
! for i in range(7):
! if str: str = str + ' '
! str = str + _center(names[i%7][:width], width)
! return str
- # Print a month's calendar
def prmonth(year, month, w = 0, l = 0):
! w = max(2, w)
! l = max(1, l)
! print _center(month_name[month] + ' ' + `year`, 7*(w+1) - 1),
! print '\n'*l,
! print weekheader(w),
! print '\n'*l,
! for week in monthcalendar(year, month):
! prweek(week, w)
! print '\n'*l,
# Spacing of month columns
! _colwidth = 7*3 - 1 # Amount printed by prweek()
! _spacing = ' '*4 # Spaces between columns
- # 3-column formatting for year calendars
def format3c(a, b, c):
! print _center(a, _colwidth),
! print _spacing,
! print _center(b, _colwidth),
! print _spacing,
! print _center(c, _colwidth)
- # Print a year's calendar
def prcal(year):
! header = weekheader(2)
! format3c('', `year`, '')
! for q in range(January, January+12, 3):
! print
! format3c(month_name[q], month_name[q+1], month_name[q+2])
! format3c(header, header, header)
! data = []
! height = 0
! for month in range(q, q+3):
! cal = monthcalendar(year, month)
! if len(cal) > height: height = len(cal)
! data.append(cal)
! for i in range(height):
! for cal in data:
! if i >= len(cal):
! print ' '*_colwidth,
! else:
! prweek(cal[i], 2)
! print _spacing,
! print
- # Unrelated but handy function to calculate Unix timestamp from GMT
EPOCH = 1970
def timegm(tuple):
! year, month, day, hour, minute, second = tuple[:6]
! assert year >= EPOCH
! assert 1 <= month <= 12
! days = 365*(year-EPOCH) + leapdays(EPOCH, year)
! for i in range(1, month):
! days = days + mdays[i]
! if month > 2 and isleap(year):
! days = days + 1
! days = days + day - 1
! hours = days*24 + hour
! minutes = hours*60 + minute
! seconds = minutes*60 + second
! return seconds
--- 21,168 ----
# Full and abbreviated names of weekdays
! day_name = ['Monday', 'Tuesday', 'Wednesday', 'Thursday',
! 'Friday', 'Saturday', 'Sunday']
day_abbr = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
# Full and abbreviated names of months (1-based arrays!!!)
! month_name = ['', 'January', 'February', 'March', 'April',
! 'May', 'June', 'July', 'August',
! 'September', 'October', 'November', 'December']
! month_abbr = [' ', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
! 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
def isleap(year):
! """Return 1 for leap years, 0 for non-leap years."""
! return year % 4 == 0 and (year % 100 <> 0 or year % 400 == 0)
def leapdays(y1, y2):
! """Return number of leap years in range [y1, y2).
! Assume y1 <= y2 and no funny (non-leap century) years."""
! return (y2+3)/4 - (y1+3)/4
def weekday(year, month, day):
! """Return weekday (0-6 ~ Mon-Sun) for year (1970-...), month (1-12), day (1-31)."""
! secs = mktime((year, month, day, 0, 0, 0, 0, 0, 0))
! tuple = localtime(secs)
! return tuple[6]
def monthrange(year, month):
! """Return weekday (0-6 ~ Mon-Sun) and number of days (28-31) for year, month."""
! if not 1 <= month <= 12: raise ValueError, 'bad month number'
! day1 = weekday(year, month, 1)
! ndays = mdays[month] + (month == February and isleap(year))
! return day1, ndays
def _monthcalendar(year, month):
! """Return a matrix representing a month's calendar.
! Each row represents a week; days outside this month are zero."""
! day1, ndays = monthrange(year, month)
! rows = []
! r7 = range(7)
! day = 1 - day1
! while day <= ndays:
! row = [0, 0, 0, 0, 0, 0, 0]
! for i in r7:
! if 1 <= day <= ndays: row[i] = day
! day = day + 1
! rows.append(row)
! return rows
_mc_cache = {}
def monthcalendar(year, month):
! """Caching interface to _monthcalendar."""
! key = (year, month)
! if _mc_cache.has_key(key):
! return _mc_cache[key]
! else:
! _mc_cache[key] = ret = _monthcalendar(year, month)
! return ret
def _center(str, width):
! """Center a string in a field."""
! n = width - len(str)
! if n <= 0: return str
! return ' '*((n+1)/2) + str + ' '*((n)/2)
# XXX The following code knows that print separates items with space!
def prweek(week, width):
! """Print a single week (no newline)."""
! for day in week:
! if day == 0: s = ''
! else: s = `day`
! print _center(s, width),
def weekheader(width):
! """Return a header for a week."""
! str = ''
! if width >= 9: names = day_name
! else: names = day_abbr
! for i in range(7):
! if str: str = str + ' '
! str = str + _center(names[i%7][:width], width)
! return str
def prmonth(year, month, w = 0, l = 0):
! """Print a month's calendar."""
! w = max(2, w)
! l = max(1, l)
! print _center(month_name[month] + ' ' + `year`, 7*(w+1) - 1),
! print '\n'*l,
! print weekheader(w),
! print '\n'*l,
! for week in monthcalendar(year, month):
! prweek(week, w)
! print '\n'*l,
# Spacing of month columns
! _colwidth = 7*3 - 1 # Amount printed by prweek()
! _spacing = ' '*4 # Spaces between columns
def format3c(a, b, c):
! """3-column formatting for year calendars"""
! print _center(a, _colwidth),
! print _spacing,
! print _center(b, _colwidth),
! print _spacing,
! print _center(c, _colwidth)
def prcal(year):
! """Print a year's calendar."""
! header = weekheader(2)
! format3c('', `year`, '')
! for q in range(January, January+12, 3):
! print
! format3c(month_name[q], month_name[q+1], month_name[q+2])
! format3c(header, header, header)
! data = []
! height = 0
! for month in range(q, q+3):
! cal = monthcalendar(year, month)
! if len(cal) > height: height = len(cal)
! data.append(cal)
! for i in range(height):
! for cal in data:
! if i >= len(cal):
! print ' '*_colwidth,
! else:
! prweek(cal[i], 2)
! print _spacing,
! print
EPOCH = 1970
def timegm(tuple):
! """Unrelated but handy function to calculate Unix timestamp from GMT."""
! year, month, day, hour, minute, second = tuple[:6]
! assert year >= EPOCH
! assert 1 <= month <= 12
! days = 365*(year-EPOCH) + leapdays(EPOCH, year)
! for i in range(1, month):
! days = days + mdays[i]
! if month > 2 and isleap(year):
! days = days + 1
! days = days + day - 1
! hours = days*24 + hour
! minutes = hours*60 + minute
! seconds = minutes*60 + second
! return seconds
Index: binhex.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/binhex.py,v
retrieving revision 1.10
retrieving revision 1.11
diff -C2 -r1.10 -r1.11
*** binhex.py 1998/03/26 20:34:13 1.10
--- binhex.py 2000/02/02 15:10:14 1.11
***************
*** 1,3 ****
--- 1,4 ----
"""binhex - Macintosh binhex compression/decompression
+
easy interface:
binhex(inputfilename, outputfilename)
***************
*** 26,30 ****
import string
import binascii
!
[...982 lines suppressed...]
! nfinfo.Flags = finfo.Flags
! ofss.SetFInfo(nfinfo)
!
! ifp.close()
def _test():
! if os.name == 'mac':
! fss, ok = macfs.PromptGetFile('File to convert:')
! if not ok:
! sys.exit(0)
! fname = fss.as_pathname()
! else:
! fname = sys.argv[1]
! binhex(fname, fname+'.hqx')
! hexbin(fname+'.hqx', fname+'.viahqx')
! #hexbin(fname, fname+'.unpacked')
! sys.exit(1)
!
if __name__ == '__main__':
! _test()
Index: bdb.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/bdb.py,v
retrieving revision 1.26
retrieving revision 1.27
diff -C2 -r1.26 -r1.27
*** bdb.py 2000/01/19 21:57:30 1.26
--- bdb.py 2000/02/02 15:10:14 1.27
***************
*** 1,3 ****
! # Debugger basics
import sys
--- 1,3 ----
! """Debugger basics"""
import sys
***************
*** 9,474 ****
[...1079 lines suppressed...]
! line = linecache.getline(fn, frame.f_lineno)
! print '+++', fn, frame.f_lineno, name, ':', string.strip(line)
! def user_return(self, frame, retval):
! print '+++ return', retval
! def user_exception(self, frame, exc_stuff):
! print '+++ exception', exc_stuff
! self.set_continue()
def foo(n):
! print 'foo(', n, ')'
! x = bar(n*10)
! print 'bar returned', x
def bar(a):
! print 'bar(', a, ')'
! return a/2
def test():
! t = Tdb()
! t.run('import bdb; bdb.foo(10)')
Index: base64.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/base64.py,v
retrieving revision 1.8
retrieving revision 1.9
diff -C2 -r1.8 -r1.9
*** base64.py 2000/01/03 15:44:40 1.8
--- base64.py 2000/02/02 15:10:14 1.9
***************
*** 1,6 ****
#! /usr/bin/env python
! # Conversions to/from base64 transport encoding as per RFC-1521.
! #
# Modified 04-Oct-95 by Jack to use binascii module
--- 1,6 ----
#! /usr/bin/env python
! """Conversions to/from base64 transport encoding as per RFC-1521."""
!
# Modified 04-Oct-95 by Jack to use binascii module
***************
*** 10,77 ****
MAXBINSIZE = (MAXLINESIZE/4)*3
- # Encode a file.
def encode(input, output):
! while 1:
! s = input.read(MAXBINSIZE)
! if not s: break
! while len(s) < MAXBINSIZE:
! ns = input.read(MAXBINSIZE-len(s))
! if not ns: break
! s = s + ns
! line = binascii.b2a_base64(s)
! output.write(line)
- # Decode a file.
def decode(input, output):
! while 1:
! line = input.readline()
! if not line: break
! s = binascii.a2b_base64(line)
! output.write(s)
def encodestring(s):
! import StringIO
! f = StringIO.StringIO(s)
! g = StringIO.StringIO()
! encode(f, g)
! return g.getvalue()
def decodestring(s):
! import StringIO
! f = StringIO.StringIO(s)
! g = StringIO.StringIO()
! decode(f, g)
! return g.getvalue()
- # Small test program
def test():
! import sys, getopt
! try:
! opts, args = getopt.getopt(sys.argv[1:], 'deut')
! except getopt.error, msg:
! sys.stdout = sys.stderr
! print msg
! print """usage: basd64 [-d] [-e] [-u] [-t] [file|-]
! -d, -u: decode
! -e: encode (default)
! -t: decode string 'Aladdin:open sesame'"""
! sys.exit(2)
! func = encode
! for o, a in opts:
! if o == '-e': func = encode
! if o == '-d': func = decode
! if o == '-u': func = decode
! if o == '-t': test1(); return
! if args and args[0] != '-':
! func(open(args[0], 'rb'), sys.stdout)
! else:
! func(sys.stdin, sys.stdout)
def test1():
! s0 = "Aladdin:open sesame"
! s1 = encodestring(s0)
! s2 = decodestring(s1)
! print s0, `s1`, s2
if __name__ == '__main__':
! test()
--- 10,79 ----
MAXBINSIZE = (MAXLINESIZE/4)*3
def encode(input, output):
! """Encode a file."""
! while 1:
! s = input.read(MAXBINSIZE)
! if not s: break
! while len(s) < MAXBINSIZE:
! ns = input.read(MAXBINSIZE-len(s))
! if not ns: break
! s = s + ns
! line = binascii.b2a_base64(s)
! output.write(line)
def decode(input, output):
! """Decode a file."""
! while 1:
! line = input.readline()
! if not line: break
! s = binascii.a2b_base64(line)
! output.write(s)
def encodestring(s):
! """Encode a string."""
! import StringIO
! f = StringIO.StringIO(s)
! g = StringIO.StringIO()
! encode(f, g)
! return g.getvalue()
def decodestring(s):
! """Decode a string."""
! import StringIO
! f = StringIO.StringIO(s)
! g = StringIO.StringIO()
! decode(f, g)
! return g.getvalue()
def test():
! """Small test program"""
! import sys, getopt
! try:
! opts, args = getopt.getopt(sys.argv[1:], 'deut')
! except getopt.error, msg:
! sys.stdout = sys.stderr
! print msg
! print """usage: basd64 [-d] [-e] [-u] [-t] [file|-]
! -d, -u: decode
! -e: encode (default)
! -t: decode string 'Aladdin:open sesame'"""
! sys.exit(2)
! func = encode
! for o, a in opts:
! if o == '-e': func = encode
! if o == '-d': func = decode
! if o == '-u': func = decode
! if o == '-t': test1(); return
! if args and args[0] != '-':
! func(open(args[0], 'rb'), sys.stdout)
! else:
! func(sys.stdin, sys.stdout)
def test1():
! s0 = "Aladdin:open sesame"
! s1 = encodestring(s0)
! s2 = decodestring(s1)
! print s0, `s1`, s2
if __name__ == '__main__':
! test()
Index: aifc.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/aifc.py,v
retrieving revision 1.34
retrieving revision 1.35
diff -C2 -r1.34 -r1.35
*** aifc.py 1999/08/26 15:50:43 1.34
--- aifc.py 2000/02/02 15:10:15 1.35
***************
*** 1,137 ****
! # Stuff to parse AIFF-C and AIFF files.
! #
! # Unless explicitly stated otherwise, the description below is true
! # both for AIFF-C files and AIFF files.
! #
! # An AIFF-C file has the following structure.
! #
! # +-----------------+
! # | FORM |
! # +-----------------+
[...1887 lines suppressed...]
! print "Reading", fn
! print "nchannels =", f.getnchannels()
! print "nframes =", f.getnframes()
! print "sampwidth =", f.getsampwidth()
! print "framerate =", f.getframerate()
! print "comptype =", f.getcomptype()
! print "compname =", f.getcompname()
! if sys.argv[2:]:
! gn = sys.argv[2]
! print "Writing", gn
! g = open(gn, 'w')
! g.setparams(f.getparams())
! while 1:
! data = f.readframes(1024)
! if not data:
! break
! g.writeframes(data)
! g.close()
! f.close()
! print "Done."
From fdrake@weyr.cnri.reston.va.us Wed Feb 2 16:30:48 2000
From: fdrake@weyr.cnri.reston.va.us (Fred L. Drake)
Date: Wed, 2 Feb 2000 11:30:48 -0500 (EST)
Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libmarshal.tex,1.16,1.16.4.1
Message-ID: <200002021630.LAA00871@weyr.cnri.reston.va.us>
Update of /projects/cvsroot/python/dist/src/Doc/lib
In directory weyr:/home/fdrake/projects/python/Doc-152p1/lib
Modified Files:
Tag: release152p1-patches
libmarshal.tex
Log Message:
In the descriptions of dump() and load(), point out that the file has
to be opened in binary mode.
Index: libmarshal.tex
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Doc/lib/libmarshal.tex,v
retrieving revision 1.16
retrieving revision 1.16.4.1
diff -C2 -r1.16 -r1.16.4.1
*** libmarshal.tex 1999/04/22 21:23:21 1.16
--- libmarshal.tex 2000/02/02 16:30:44 1.16.4.1
***************
*** 63,67 ****
type. The file must be an open file object such as
\code{sys.stdout} or returned by \function{open()} or
! \function{posix.popen()}.
If the value has (or contains an object that has) an unsupported type,
--- 63,68 ----
type. The file must be an open file object such as
\code{sys.stdout} or returned by \function{open()} or
! \function{posix.popen()}. It must be opened in binary mode
! (\code{'wb'} or \code{'w+b'}).
If the value has (or contains an object that has) an unsupported type,
***************
*** 74,78 ****
Read one value from the open file and return it. If no valid value
is read, raise \exception{EOFError}, \exception{ValueError} or
! \exception{TypeError}. The file must be an open file object.
\strong{Warning:} If an object containing an unsupported type was
--- 75,80 ----
Read one value from the open file and return it. If no valid value
is read, raise \exception{EOFError}, \exception{ValueError} or
! \exception{TypeError}. The file must be an open file object opened
! in binary mode (\code{'rb'} or \code{'r+b'}).
\strong{Warning:} If an object containing an unsupported type was
From guido@cnri.reston.va.us Wed Feb 2 16:51:09 2000
From: guido@cnri.reston.va.us (Guido van Rossum)
Date: Wed, 2 Feb 2000 11:51:09 -0500 (EST)
Subject: [Python-checkins] CVS: python/dist/src/Lib gzip.py,1.14,1.15
Message-ID: <200002021651.LAA22922@eric.cnri.reston.va.us>
Update of /projects/cvsroot/python/dist/src/Lib
In directory eric:/projects/python/develop/guido/src/Lib
Modified Files:
gzip.py
Log Message:
Make read() and readlines() conform more to the file object interface:
the default arg for read() is -1, not None, and readlines() has an
optional argument (which for now is ignored).
Index: gzip.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/gzip.py,v
retrieving revision 1.14
retrieving revision 1.15
diff -C2 -r1.14 -r1.15
*** gzip.py 1999/09/06 16:34:51 1.14
--- gzip.py 2000/02/02 16:51:06 1.15
***************
*** 140,149 ****
self.write(string.join(lines))
! def read(self, size=None):
if self.extrasize <= 0 and self.fileobj is None:
return ''
readsize = 1024
! if not size: # get the whole thing
try:
while 1:
--- 140,149 ----
self.write(string.join(lines))
! def read(self, size=-1):
if self.extrasize <= 0 and self.fileobj is None:
return ''
readsize = 1024
! if size < 0: # get the whole thing
try:
while 1:
***************
*** 282,286 ****
readsize = readsize * 2
! def readlines(self):
buf = self.read()
lines = string.split(buf, '\n')
--- 282,286 ----
readsize = readsize * 2
! def readlines(self, ignored=None):
buf = self.read()
lines = string.split(buf, '\n')
From guido@cnri.reston.va.us Wed Feb 2 16:54:42 2000
From: guido@cnri.reston.va.us (Guido van Rossum)
Date: Wed, 2 Feb 2000 11:54:42 -0500 (EST)
Subject: [Python-checkins] CVS: python/dist/src/Lib ntpath.py,1.21,1.22
Message-ID: <200002021654.LAA22950@eric.cnri.reston.va.us>
Update of /projects/cvsroot/python/dist/src/Lib
In directory eric:/projects/python/develop/guido/src/Lib
Modified Files:
ntpath.py
Log Message:
Optimize abspath() slightly for the case that win32api can't be
imported; in that case, abspath is replaced by a fallback version.
Index: ntpath.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/ntpath.py,v
retrieving revision 1.21
retrieving revision 1.22
diff -C2 -r1.21 -r1.22
*** ntpath.py 1999/11/30 15:00:00 1.21
--- ntpath.py 2000/02/02 16:54:39 1.22
***************
*** 404,413 ****
try:
import win32api
- try:
- path = win32api.GetFullPathName(path)
- except win32api.error:
- pass # Bad path - return unchanged.
except ImportError:
! if not isabs(path):
! path = join(os.getcwd(), path)
return normpath(path)
--- 404,418 ----
try:
import win32api
except ImportError:
! global abspath
! def _abspath(path):
! if not isabs(path):
! path = join(os.getcwd(), path)
! return normpath(path)
! abspath = _abspath
! return _abspath(path)
! try:
! path = win32api.GetFullPathName(path)
! except win32api.error:
! pass # Bad path - return unchanged.
return normpath(path)
From guido@cnri.reston.va.us Wed Feb 2 16:57:34 2000
From: guido@cnri.reston.va.us (Guido van Rossum)
Date: Wed, 2 Feb 2000 11:57:34 -0500 (EST)
Subject: [Python-checkins] CVS: python/dist/src/Lib/plat-win socket.py,1.6,1.7
Message-ID: <200002021657.LAA22978@eric.cnri.reston.va.us>
Update of /projects/cvsroot/python/dist/src/Lib/plat-win
In directory eric:/projects/python/develop/guido/src/Lib/plat-win
Modified Files:
socket.py
Log Message:
In _fileobject, optimize read() a bit (it could be really slow), and
remove "import string" -- use string methods instead!
Index: socket.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/plat-win/socket.py,v
retrieving revision 1.6
retrieving revision 1.7
diff -C2 -r1.6 -r1.7
*** socket.py 1998/05/06 13:48:04 1.6
--- socket.py 2000/02/02 16:57:32 1.7
***************
*** 97,125 ****
def read(self, n=-1):
if n >= 0:
! while len(self._rbuf) < n:
! new = self._sock.recv(self._rbufsize)
if not new: break
! self._rbuf = self._rbuf + new
! data, self._rbuf = self._rbuf[:n], self._rbuf[n:]
! return data
while 1:
! new = self._sock.recv(self._rbufsize)
if not new: break
! self._rbuf = self._rbuf + new
! data, self._rbuf = self._rbuf, ""
! return data
! def readline(self):
! import string
data = ""
! i = string.find(self._rbuf, '\n')
! while i < 0:
new = self._sock.recv(self._rbufsize)
if not new: break
! i = string.find(new, '\n')
if i >= 0: i = i + len(self._rbuf)
self._rbuf = self._rbuf + new
if i < 0: i = len(self._rbuf)
else: i = i+1
data, self._rbuf = self._rbuf[:i], self._rbuf[i:]
return data
--- 97,141 ----
def read(self, n=-1):
if n >= 0:
! k = len(self._rbuf)
! if n <= k:
! data = self._rbuf[:n]
! self._rbuf = self._rbuf[n:]
! return data
! n = n - k
! l = [self._rbuf]
! self._rbuf = ""
! while n > 0:
! new = self._sock.recv(max(n, self._rbufsize))
if not new: break
! k = len(new)
! if k > n:
! l.append(new[:n])
! self._rbuf = new[n:]
! break
! l.append(new)
! n = n - k
! return "".join(l)
! k = max(512, self._rbufsize)
! l = [self._rbuf]
! self._rbuf = ""
while 1:
! new = self._sock.recv(k)
if not new: break
! l.append(new)
! k = min(k*2, 1024**2)
! return "".join(l)
! def readline(self, limit=-1):
data = ""
! i = self._rbuf.find('\n')
! while i < 0 and not (0 < limit <= len(self._rbuf)):
new = self._sock.recv(self._rbufsize)
if not new: break
! i = new.find('\n')
if i >= 0: i = i + len(self._rbuf)
self._rbuf = self._rbuf + new
if i < 0: i = len(self._rbuf)
else: i = i+1
+ if 0 <= limit < len(self._rbuf): i = limit
data, self._rbuf = self._rbuf[:i], self._rbuf[i:]
return data
From guido@cnri.reston.va.us Thu Feb 3 00:41:24 2000
From: guido@cnri.reston.va.us (Guido van Rossum)
Date: Wed, 2 Feb 2000 19:41:24 -0500 (EST)
Subject: [Python-checkins] CVS: python/dist/src/Lib filecmp.py,1.1,1.2
Message-ID: <200002030041.TAA25281@eric.cnri.reston.va.us>
Update of /projects/cvsroot/python/dist/src/Lib
In directory eric:/projects/python/develop/guido/src/Lib
Modified Files:
filecmp.py
Log Message:
# module filecmp
# combo of old cmp, cmpcache and dircmp with redundancies removed
#
# bugs fixed:
# dircmp.dircmp was not ignoring IGNORES
# old stuff could falsely report files as "identical" when contents actually differed
#
# enhancements:
# dircmp has a more straightforward interface
#cmp enhanced by Moshe Zadca
#dircmp enhanced byGordon McMillan
[some layout changes by GvR]
Index: filecmp.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/filecmp.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -r1.1 -r1.2
*** filecmp.py 1999/10/26 14:02:01 1.1
--- filecmp.py 2000/02/03 00:41:22 1.2
***************
*** 1,57 ****
! """Compare files."""
! import os, stat, statcache
_cache = {}
BUFSIZE=8*1024
! def cmp(f1, f2, shallow=1,use_statcache=0):
! """Compare two files.
! Arguments:
! f1 -- First file name
! f2 -- Second file name
! shallow -- Just check stat signature (do not read the files).
! defaults to 1.
! use_statcache -- Do not stat() each file directly: go through
! the statcache module for more efficiency.
! Return value:
! integer -- 1 if the files are the same, 0 otherwise.
! This function uses a cache for past comparisons and the results,
! with a cache invalidation mechanism relying on stale signatures.
! Of course, if 'use_statcache' is true, this mechanism is defeated,
! and the cache will never grow stale.
! """
! stat_function = (os.stat, statcache.stat)[use_statcache]
! s1, s2 = _sig(stat_function(f1)), _sig(stat_function(f2))
! if s1[0]!=stat.S_IFREG or s2[0]!=stat.S_IFREG: return 0
! if shallow and s1 == s2: return 1
! if s1[1]!=s2[1]: return 0
! result = _cache.get((f1, f2))
! if result and (s1, s2)==result[:2]:
! return result[2]
! outcome = _do_cmp(f1, f2)
! _cache[f1, f2] = s1, s2, outcome
! return outcome
def _sig(st):
! return (stat.S_IFMT(st[stat.ST_MODE]),
! st[stat.ST_SIZE],
! st[stat.ST_MTIME])
def _do_cmp(f1, f2):
! bufsize = BUFSIZE
! fp1 , fp2 = open(f1, 'rb'), open(f2, 'rb')
! while 1:
! b1, b2 = fp1.read(bufsize), fp2.read(bufsize)
! if b1!=b2: return 0
! if not b1: return 1
--- 1,318 ----
! """Utilities for comparing files and directories.
! Classes:
! dircmp
+ Functions:
+ cmp(f1, f2, shallow=1, use_statcache=0) -> int
+ cmpfiles(a, b, common) -> ([], [], [])
+
+ """
+
+ import os
+ import stat
+ import statcache
+
_cache = {}
BUFSIZE=8*1024
! def cmp(f1, f2, shallow=1,use_statcache=0):
! """Compare two files.
! Arguments:
! f1 -- First file name
! f2 -- Second file name
! shallow -- Just check stat signature (do not read the files).
! defaults to 1.
! use_statcache -- Do not stat() each file directly: go through
! the statcache module for more efficiency.
! Return value:
! integer -- 1 if the files are the same, 0 otherwise.
! This function uses a cache for past comparisons and the results,
! with a cache invalidation mechanism relying on stale signatures.
! Of course, if 'use_statcache' is true, this mechanism is defeated,
! and the cache will never grow stale.
! """
! stat_function = (os.stat, statcache.stat)[use_statcache]
! s1, s2 = _sig(stat_function(f1)), _sig(stat_function(f2))
! if s1[0]!=stat.S_IFREG or s2[0]!=stat.S_IFREG: return 0
! if shallow and s1 == s2: return 1
! if s1[1]!=s2[1]: return 0
! result = _cache.get((f1, f2))
! if result and (s1, s2)==result[:2]:
! return result[2]
! outcome = _do_cmp(f1, f2)
! _cache[f1, f2] = s1, s2, outcome
! return outcome
def _sig(st):
! return (stat.S_IFMT(st[stat.ST_MODE]),
! st[stat.ST_SIZE],
! st[stat.ST_MTIME])
def _do_cmp(f1, f2):
! bufsize = BUFSIZE
! fp1 , fp2 = open(f1, 'rb'), open(f2, 'rb')
! while 1:
! b1, b2 = fp1.read(bufsize), fp2.read(bufsize)
! if b1!=b2: return 0
! if not b1: return 1
!
! # Directory comparison class.
! #
! class dircmp:
! """A class that manages the comparison of 2 directories.
!
! dircmp(a,b,ignore=None,hide=None)
! A and B are directories.
! IGNORE is a list of names to ignore,
! defaults to ['RCS', 'CVS', 'tags'].
! HIDE is a list of names to hide,
! defaults to [os.curdir, os.pardir].
!
! High level usage:
! x = dircmp(dir1, dir2)
! x.report() -> prints a report on the differences between dir1 and dir2
! or
! x.report_partial_closure() -> prints report on differences between dir1
! and dir2, and reports on common immediate subdirectories.
! x.report_full_closure() -> like report_partial_closure,
! but fully recursive.
!
! Attributes:
! left_list, right_list: The files in dir1 and dir2,
! filtered by hide and ignore.
! common: a list of names in both dir1 and dir2.
! left_only, right_only: names only in dir1, dir2.
! common_dirs: subdirectories in both dir1 and dir2.
! common_files: files in both dir1 and dir2.
! common_funny: names in both dir1 and dir2 where the type differs between
! dir1 and dir2, or the name is not stat-able.
! same_files: list of identical files.
! diff_files: list of filenames which differ.
! funny_files: list of files which could not be compared.
! subdirs: a dictionary of dircmp objects, keyed by names in common_dirs.
! """
!
! def __init__(self, a, b, ignore=None, hide=None): # Initialize
! self.left = a
! self.right = b
! if hide is None:
! self.hide = [os.curdir, os.pardir] # Names never to be shown
! else:
! self.hide = hide
! if ignore is None:
! self.ignore = ['RCS', 'CVS', 'tags'] # Names ignored in comparison
! else:
! self.ignore = ignore
!
! def phase0(self): # Compare everything except common subdirectories
! self.left_list = _filter(os.listdir(self.left),
! self.hide+self.ignore)
! self.right_list = _filter(os.listdir(self.right),
! self.hide+self.ignore)
! self.left_list.sort()
! self.right_list.sort()
!
! __p4_attrs = ('subdirs',)
! __p3_attrs = ('same_files', 'diff_files', 'funny_files')
! __p2_attrs = ('common_dirs', 'common_files', 'common_funny')
! __p1_attrs = ('common', 'left_only', 'right_only')
! __p0_attrs = ('left_list', 'right_list')
!
! def __getattr__(self, attr):
! if attr in self.__p4_attrs:
! self.phase4()
! elif attr in self.__p3_attrs:
! self.phase3()
! elif attr in self.__p2_attrs:
! self.phase2()
! elif attr in self.__p1_attrs:
! self.phase1()
! elif attr in self.__p0_attrs:
! self.phase0()
! else:
! raise AttributeError, attr
! return getattr(self, attr)
!
! def phase1(self): # Compute common names
! a_only, b_only = [], []
! common = {}
! b = {}
! for fnm in self.right_list:
! b[fnm] = 1
! for x in self.left_list:
! if b.get(x, 0):
! common[x] = 1
! else:
! a_only.append(x)
! for x in self.right_list:
! if common.get(x, 0):
! pass
! else:
! b_only.append(x)
! self.common = common.keys()
! self.left_only = a_only
! self.right_only = b_only
!
! def phase2(self): # Distinguish files, directories, funnies
! self.common_dirs = []
! self.common_files = []
! self.common_funny = []
!
! for x in self.common:
! a_path = os.path.join(self.left, x)
! b_path = os.path.join(self.right, x)
!
! ok = 1
! try:
! a_stat = statcache.stat(a_path)
! except os.error, why:
! # print 'Can\'t stat', a_path, ':', why[1]
! ok = 0
! try:
! b_stat = statcache.stat(b_path)
! except os.error, why:
! # print 'Can\'t stat', b_path, ':', why[1]
! ok = 0
!
! if ok:
! a_type = stat.S_IFMT(a_stat[stat.ST_MODE])
! b_type = stat.S_IFMT(b_stat[stat.ST_MODE])
! if a_type <> b_type:
! self.common_funny.append(x)
! elif stat.S_ISDIR(a_type):
! self.common_dirs.append(x)
! elif stat.S_ISREG(a_type):
! self.common_files.append(x)
! else:
! self.common_funny.append(x)
! else:
! self.common_funny.append(x)
!
! def phase3(self): # Find out differences between common files
! xx = cmpfiles(self.left, self.right, self.common_files)
! self.same_files, self.diff_files, self.funny_files = xx
!
! def phase4(self): # Find out differences between common subdirectories
! # A new dircmp object is created for each common subdirectory,
! # these are stored in a dictionary indexed by filename.
! # The hide and ignore properties are inherited from the parent
! self.subdirs = {}
! for x in self.common_dirs:
! a_x = os.path.join(self.left, x)
! b_x = os.path.join(self.right, x)
! self.subdirs[x] = dircmp(a_x, b_x, self.ignore, self.hide)
!
! def phase4_closure(self): # Recursively call phase4() on subdirectories
! self.phase4()
! for x in self.subdirs.keys():
! self.subdirs[x].phase4_closure()
!
! def report(self): # Print a report on the differences between a and b
! # Output format is purposely lousy
! print 'diff', self.left, self.right
! if self.left_only:
! self.left_only.sort()
! print 'Only in', self.left, ':', self.left_only
! if self.right_only:
! self.right_only.sort()
! print 'Only in', self.right, ':', self.right_only
! if self.same_files:
! self.same_files.sort()
! print 'Identical files :', self.same_files
! if self.diff_files:
! self.diff_files.sort()
! print 'Differing files :', self.diff_files
! if self.funny_files:
! self.funny_files.sort()
! print 'Trouble with common files :', self.funny_files
! if self.common_dirs:
! self.common_dirs.sort()
! print 'Common subdirectories :', self.common_dirs
! if self.common_funny:
! self.common_funny.sort()
! print 'Common funny cases :', self.common_funny
!
! def report_partial_closure(self): # Print reports on self and on subdirs
! self.report()
! for x in self.subdirs.keys():
! print
! self.subdirs[x].report()
!
! def report_full_closure(self): # Report on self and subdirs recursively
! self.report()
! for x in self.subdirs.keys():
! print
! self.subdirs[x].report_full_closure()
!
!
! # Compare common files in two directories.
! # Return:
! # - files that compare equal
! # - files that compare different
! # - funny cases (can't stat etc.)
! #
! def cmpfiles(a, b, common):
! """Compare common files in two directories.
!
! cmpfiles(a,b,common)
! A and B are directory names
! COMMON is a list of file names
! returns a tuple of three lists:
! files that compare equal
! files that are different
! filenames that aren't regular files."""
!
! res = ([], [], [])
! for x in common:
! res[_cmp(os.path.join(a, x), os.path.join(b, x))].append(x)
! return res
!
!
! # Compare two files.
! # Return:
! # 0 for equal
! # 1 for different
! # 2 for funny cases (can't stat, etc.)
! #
! def _cmp(a, b):
! try:
! return not abs(cmp(a, b))
! except os.error:
! return 2
!
!
! # Return a copy with items that occur in skip removed.
! #
! def _filter(list, skip):
! result = []
! for item in list:
! if item not in skip: result.append(item)
! return result
!
!
! # Demonstration and testing.
! #
! def demo():
! import sys
! import getopt
! options, args = getopt.getopt(sys.argv[1:], 'r')
! if len(args) <> 2: raise getopt.error, 'need exactly two args'
! dd = dircmp(args[0], args[1])
! if ('-r', '') in options:
! dd.report_full_closure()
! else:
! dd.report()
!
! if __name__ == '__main__':
! demo()
From guido@cnri.reston.va.us Thu Feb 3 13:42:53 2000
From: guido@cnri.reston.va.us (Guido van Rossum)
Date: Thu, 3 Feb 2000 08:42:53 -0500 (EST)
Subject: [Python-checkins] CVS: python/dist/src configure.in,1.114,1.115
Message-ID: <200002031342.IAA26792@eric.cnri.reston.va.us>
Update of /projects/cvsroot/python/dist/src
In directory eric:/projects/python/develop/guido/src
Modified Files:
configure.in
Log Message:
According to Harri Pasanen, the Solaris+gcc test for LINKFORSHARED
needed an adaptation for the latest gcc -- we need to grep stderr as
well as stdout for the magic string BFD. (Does anybody know what BFD
means?)
Index: configure.in
===================================================================
RCS file: /projects/cvsroot/python/dist/src/configure.in,v
retrieving revision 1.114
retrieving revision 1.115
diff -C2 -r1.114 -r1.115
*** configure.in 1999/12/20 21:27:22 1.114
--- configure.in 2000/02/03 13:42:50 1.115
***************
*** 1,4 ****
dnl Process this file with autoconf 2.0 or later to make a configure script.
! AC_REVISION($Revision: 1.114 $)
AC_PREREQ(2.0)
AC_INIT(Include/object.h)
--- 1,4 ----
dnl Process this file with autoconf 2.0 or later to make a configure script.
! AC_REVISION($Revision: 1.115 $)
AC_PREREQ(2.0)
AC_INIT(Include/object.h)
***************
*** 566,570 ****
SunOS/5*) case $CC in
*gcc*)
! if $CC -Xlinker -V 2>/dev/null | grep BFD >/dev/null
then
LINKFORSHARED="-Xlinker --export-dynamic"
--- 566,570 ----
SunOS/5*) case $CC in
*gcc*)
! if $CC -Xlinker -V 2>&1 | grep BFD >/dev/null
then
LINKFORSHARED="-Xlinker --export-dynamic"
From guido@cnri.reston.va.us Thu Feb 3 13:50:27 2000
From: guido@cnri.reston.va.us (Guido van Rossum)
Date: Thu, 3 Feb 2000 08:50:27 -0500 (EST)
Subject: [Python-checkins] CVS: python/dist/src configure,1.106,1.107
Message-ID: <200002031350.IAA27300@eric.cnri.reston.va.us>
Update of /projects/cvsroot/python/dist/src
In directory eric:/projects/python/develop/guido/src
Modified Files:
configure
Log Message:
According to Harri Pasanen, the Solaris+gcc test for LINKFORSHARED
needed an adaptation for the latest gcc -- we need to grep stderr as
well as stdout for the magic string BFD. (Does anybody know what BFD
means?)
Index: configure
===================================================================
RCS file: /projects/cvsroot/python/dist/src/configure,v
retrieving revision 1.106
retrieving revision 1.107
diff -C2 -r1.106 -r1.107
*** configure 1999/12/20 21:27:22 1.106
--- configure 2000/02/03 13:50:24 1.107
***************
*** 1,5 ****
#! /bin/sh
! # From configure.in Revision: 1.114
# Guess values for system-dependent variables and create Makefiles.
--- 1,5 ----
#! /bin/sh
! # From configure.in Revision: 1.115
# Guess values for system-dependent variables and create Makefiles.
***************
*** 2356,2360 ****
SunOS/5*) case $CC in
*gcc*)
! if $CC -Xlinker -V 2>/dev/null | grep BFD >/dev/null
then
LINKFORSHARED="-Xlinker --export-dynamic"
--- 2356,2360 ----
SunOS/5*) case $CC in
*gcc*)
! if $CC -Xlinker -V 2>&1 | grep BFD >/dev/null
then
LINKFORSHARED="-Xlinker --export-dynamic"
From gstein@lyra.org Thu Feb 3 13:56:11 2000
From: gstein@lyra.org (Greg Stein)
Date: Thu, 3 Feb 2000 05:56:11 -0800 (PST)
Subject: [Python-checkins] CVS: python/dist/src configure,1.106,1.107
In-Reply-To: <200002031350.IAA27300@eric.cnri.reston.va.us>
Message-ID:
In some contexts, it means "Big Fucking Deal". I doubt that is the meaning
in this situation, though.
:-)
On Thu, 3 Feb 2000, Guido van Rossum wrote:
> Update of /projects/cvsroot/python/dist/src
> In directory eric:/projects/python/develop/guido/src
>
> Modified Files:
> configure
> Log Message:
> According to Harri Pasanen, the Solaris+gcc test for LINKFORSHARED
> needed an adaptation for the latest gcc -- we need to grep stderr as
> well as stdout for the magic string BFD. (Does anybody know what BFD
> means?)
>
>
> Index: configure
> ===================================================================
> RCS file: /projects/cvsroot/python/dist/src/configure,v
> retrieving revision 1.106
> retrieving revision 1.107
> diff -C2 -r1.106 -r1.107
> *** configure 1999/12/20 21:27:22 1.106
> --- configure 2000/02/03 13:50:24 1.107
> ***************
> *** 1,5 ****
> #! /bin/sh
>
> ! # From configure.in Revision: 1.114
>
> # Guess values for system-dependent variables and create Makefiles.
> --- 1,5 ----
> #! /bin/sh
>
> ! # From configure.in Revision: 1.115
>
> # Guess values for system-dependent variables and create Makefiles.
> ***************
> *** 2356,2360 ****
> SunOS/5*) case $CC in
> *gcc*)
> ! if $CC -Xlinker -V 2>/dev/null | grep BFD >/dev/null
> then
> LINKFORSHARED="-Xlinker --export-dynamic"
> --- 2356,2360 ----
> SunOS/5*) case $CC in
> *gcc*)
> ! if $CC -Xlinker -V 2>&1 | grep BFD >/dev/null
> then
> LINKFORSHARED="-Xlinker --export-dynamic"
>
>
> _______________________________________________
> Python-checkins mailing list
> Python-checkins@python.org
> http://www.python.org/mailman/listinfo/python-checkins
>
--
Greg Stein, http://www.lyra.org/
From Vladimir.Marangozov@inrialpes.fr Thu Feb 3 14:15:56 2000
From: Vladimir.Marangozov@inrialpes.fr (Vladimir Marangozov)
Date: Thu, 3 Feb 2000 15:15:56 +0100 (CET)
Subject: [Python-checkins] BFD
Message-ID: <200002031415.PAA09557@python.inrialpes.fr>
Oops, my "pycvs" alias wasn't set and the Cc: failed.
Forwarded message:
> From marangoz Thu Feb 3 15:11:02 2000
> Subject: Re: [Python-checkins] CVS: python/dist/src configure,1.106,1.107
> To: guido@cnri.reston.va.us (Guido van Rossum)
> Date: Thu, 3 Feb 2000 15:11:02 +0100 (CET)
> Cc: pycvs
> In-Reply-To: <200002031350.IAA27300@eric.cnri.reston.va.us> from "Guido van Rossum" at Feb 03, 2000 08:50:27 AM
> Reply-To: Vladimir.Marangozov@inrialpes.fr
> X-Mailer: ELM [version 2.5 PL1]
> Content-Length: 898
>
> Guido van Rossum wrote:
> >
> > Update of /projects/cvsroot/python/dist/src
> > In directory eric:/projects/python/develop/guido/src
> >
> > Modified Files:
> > configure
> > Log Message:
> > According to Harri Pasanen, the Solaris+gcc test for LINKFORSHARED
> > needed an adaptation for the latest gcc -- we need to grep stderr as
> > well as stdout for the magic string BFD. (Does anybody know what BFD
> > means?)
>
> BFD stands for Binary File Descriptor. It's 1) a library used by most GNU
> tools, especially in GNU binutils, and more precisely 2) an internal format/
> structure + an interface allowing different tools to manipulate object files
> in a uniform way.
>
> I don't know how this relates to the build on Solaris + GCC, so I'm
> trusting Harri and you for that...
>
> --
> Vladimir MARANGOZOV | Vladimir.Marangozov@inrialpes.fr
> http://sirac.inrialpes.fr/~marangoz | tel:(+33-4)76615277 fax:76615252
>
--
Vladimir MARANGOZOV | Vladimir.Marangozov@inrialpes.fr
http://sirac.inrialpes.fr/~marangoz | tel:(+33-4)76615277 fax:76615252
From fdrake@weyr.cnri.reston.va.us Thu Feb 3 15:25:35 2000
From: fdrake@weyr.cnri.reston.va.us (Fred L. Drake)
Date: Thu, 3 Feb 2000 10:25:35 -0500 (EST)
Subject: [Python-checkins] CVS: python/dist/src/Lib/lib-old cmp.py,NONE,1.1 cmpcache.py,NONE,1.1 dircmp.py,NONE,1.1
Message-ID: <200002031525.KAA02769@weyr.cnri.reston.va.us>
Update of /projects/cvsroot/python/dist/src/Lib/lib-old
In directory weyr:/home/fdrake/projects/python/Lib/lib-old
Added Files:
cmp.py cmpcache.py dircmp.py
Log Message:
These modules are now declared obsolete.
From fdrake@weyr.cnri.reston.va.us Thu Feb 3 15:26:19 2000
From: fdrake@weyr.cnri.reston.va.us (Fred L. Drake)
Date: Thu, 3 Feb 2000 10:26:19 -0500 (EST)
Subject: [Python-checkins] CVS: python/dist/src/Lib cmp.py,1.8,NONE cmpcache.py,1.8,NONE dircmp.py,1.8,NONE
Message-ID: <200002031526.KAA02800@weyr.cnri.reston.va.us>
Update of /projects/cvsroot/python/dist/src/Lib
In directory weyr:/home/fdrake/projects/python/Lib
Removed Files:
cmp.py cmpcache.py dircmp.py
Log Message:
These modules are now declared obsolete.
From fdrake@weyr.cnri.reston.va.us Thu Feb 3 15:27:29 2000
From: fdrake@weyr.cnri.reston.va.us (Fred L. Drake)
Date: Thu, 3 Feb 2000 10:27:29 -0500 (EST)
Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libundoc.tex,1.71,1.72
Message-ID: <200002031527.KAA02833@weyr.cnri.reston.va.us>
Update of /projects/cvsroot/python/dist/src/Doc/lib
In directory weyr:/home/fdrake/projects/python/Doc/lib
Modified Files:
libundoc.tex
Log Message:
The dircmp module is now obsolete.
Index: libundoc.tex
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Doc/lib/libundoc.tex,v
retrieving revision 1.71
retrieving revision 1.72
diff -C2 -r1.71 -r1.72
*** libundoc.tex 1999/12/01 18:44:09 1.71
--- libundoc.tex 2000/02/03 15:27:26 1.72
***************
*** 36,42 ****
\begin{description}
- \item[\module{dircmp}]
- --- class to build directory diff tools on (may become a demo or tool)
-
\item[\module{bdb}]
--- A generic Python debugger base class (used by pdb)
--- 36,39 ----
***************
*** 109,112 ****
--- 106,112 ----
\member{co.co_name}, \member{func.func_name},
\member{co.co_firstlineno}).
+
+ \item[\module{dircmp}]
+ --- class to build directory diff tools on (may become a demo or tool)
\item[\module{dump}]
From guido@cnri.reston.va.us Thu Feb 3 17:19:38 2000
From: guido@cnri.reston.va.us (Guido van Rossum)
Date: Thu, 3 Feb 2000 12:19:38 -0500 (EST)
Subject: [Python-checkins] CVS: python/dist/src/PCbuild _tkinter.dsp,1.9,1.10 parser.dsp,1.5,1.6 python.dsp,1.7,1.8 python15.dsp,1.10,1.11 pythonw.dsp,1.6,1.7 zlib.dsp,1.7,1.8
Message-ID: <200002031719.MAA29329@eric.cnri.reston.va.us>
Update of /projects/cvsroot/python/dist/src/PCbuild
In directory eric:/projects/python/develop/guido/src/PCbuild
Modified Files:
_tkinter.dsp parser.dsp python.dsp python15.dsp pythonw.dsp
zlib.dsp
Log Message:
Mark Hammond renames the x86 projects back to what they were named
before the patch by Trent Mick. Since he now also works for
ActiveState, I suppose he overrides Trent. :-)
Index: _tkinter.dsp
===================================================================
RCS file: /projects/cvsroot/python/dist/src/PCbuild/_tkinter.dsp,v
retrieving revision 1.9
retrieving revision 1.10
diff -C2 -r1.9 -r1.10
*** _tkinter.dsp 2000/01/21 00:03:42 1.9
--- _tkinter.dsp 2000/02/03 17:19:35 1.10
***************
*** 21,26 ****
!MESSAGE "_tkinter - Win32 Alpha Debug" (based on "Win32 (ALPHA) Dynamic-Link Library")
!MESSAGE "_tkinter - Win32 Alpha Release" (based on "Win32 (ALPHA) Dynamic-Link Library")
! !MESSAGE "_tkinter - Win32 x86 Debug" (based on "Win32 (x86) Dynamic-Link Library")
! !MESSAGE "_tkinter - Win32 x86 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
--- 21,26 ----
!MESSAGE "_tkinter - Win32 Alpha Debug" (based on "Win32 (ALPHA) Dynamic-Link Library")
!MESSAGE "_tkinter - Win32 Alpha Release" (based on "Win32 (ALPHA) Dynamic-Link Library")
! !MESSAGE "_tkinter - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
! !MESSAGE "_tkinter - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
***************
*** 30,34 ****
# PROP Scc_LocalPath "..\..\.."
! !IF "$(CFG)" == "_tkinter - Win32 x86 Release"
# PROP BASE Use_MFC 0
--- 30,34 ----
# PROP Scc_LocalPath "..\..\.."
! !IF "$(CFG)" == "_tkinter - Win32 Release"
# PROP BASE Use_MFC 0
***************
*** 61,65 ****
# SUBTRACT LINK32 /pdb:none
! !ELSEIF "$(CFG)" == "_tkinter - Win32 x86 Debug"
# PROP BASE Use_MFC 0
--- 61,65 ----
# SUBTRACT LINK32 /pdb:none
! !ELSEIF "$(CFG)" == "_tkinter - Win32 Debug"
# PROP BASE Use_MFC 0
***************
*** 160,165 ****
# Begin Target
! # Name "_tkinter - Win32 x86 Release"
! # Name "_tkinter - Win32 x86 Debug"
# Name "_tkinter - Win32 Alpha Debug"
# Name "_tkinter - Win32 Alpha Release"
--- 160,165 ----
# Begin Target
! # Name "_tkinter - Win32 Release"
! # Name "_tkinter - Win32 Debug"
# Name "_tkinter - Win32 Alpha Debug"
# Name "_tkinter - Win32 Alpha Release"
***************
*** 168,174 ****
SOURCE=..\Modules\_tkinter.c
! !IF "$(CFG)" == "_tkinter - Win32 x86 Release"
! !ELSEIF "$(CFG)" == "_tkinter - Win32 x86 Debug"
!ELSEIF "$(CFG)" == "_tkinter - Win32 Alpha Debug"
--- 168,174 ----
SOURCE=..\Modules\_tkinter.c
! !IF "$(CFG)" == "_tkinter - Win32 Release"
! !ELSEIF "$(CFG)" == "_tkinter - Win32 Debug"
!ELSEIF "$(CFG)" == "_tkinter - Win32 Alpha Debug"
***************
*** 183,189 ****
SOURCE=..\Modules\tkappinit.c
! !IF "$(CFG)" == "_tkinter - Win32 x86 Release"
! !ELSEIF "$(CFG)" == "_tkinter - Win32 x86 Debug"
!ELSEIF "$(CFG)" == "_tkinter - Win32 Alpha Debug"
--- 183,189 ----
SOURCE=..\Modules\tkappinit.c
! !IF "$(CFG)" == "_tkinter - Win32 Release"
! !ELSEIF "$(CFG)" == "_tkinter - Win32 Debug"
!ELSEIF "$(CFG)" == "_tkinter - Win32 Alpha Debug"
Index: parser.dsp
===================================================================
RCS file: /projects/cvsroot/python/dist/src/PCbuild/parser.dsp,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -r1.5 -r1.6
*** parser.dsp 2000/01/20 21:31:41 1.5
--- parser.dsp 2000/02/03 17:19:35 1.6
***************
*** 19,24 ****
!MESSAGE Possible choices for configuration are:
!MESSAGE
! !MESSAGE "parser - Win32 x86 Release" (based on "Win32 (x86) Dynamic-Link Library")
! !MESSAGE "parser - Win32 x86 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "parser - Win32 Alpha Debug" (based on "Win32 (ALPHA) Dynamic-Link Library")
!MESSAGE "parser - Win32 Alpha Release" (based on "Win32 (ALPHA) Dynamic-Link Library")
--- 19,24 ----
!MESSAGE Possible choices for configuration are:
!MESSAGE
! !MESSAGE "parser - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
! !MESSAGE "parser - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "parser - Win32 Alpha Debug" (based on "Win32 (ALPHA) Dynamic-Link Library")
!MESSAGE "parser - Win32 Alpha Release" (based on "Win32 (ALPHA) Dynamic-Link Library")
***************
*** 30,34 ****
# PROP Scc_LocalPath ".."
! !IF "$(CFG)" == "parser - Win32 x86 Release"
# PROP BASE Use_MFC 0
--- 30,34 ----
# PROP Scc_LocalPath ".."
! !IF "$(CFG)" == "parser - Win32 Release"
# PROP BASE Use_MFC 0
***************
*** 61,65 ****
# SUBTRACT LINK32 /pdb:none
! !ELSEIF "$(CFG)" == "parser - Win32 x86 Debug"
# PROP BASE Use_MFC 0
--- 61,65 ----
# SUBTRACT LINK32 /pdb:none
! !ELSEIF "$(CFG)" == "parser - Win32 Debug"
# PROP BASE Use_MFC 0
***************
*** 160,165 ****
# Begin Target
! # Name "parser - Win32 x86 Release"
! # Name "parser - Win32 x86 Debug"
# Name "parser - Win32 Alpha Debug"
# Name "parser - Win32 Alpha Release"
--- 160,165 ----
# Begin Target
! # Name "parser - Win32 Release"
! # Name "parser - Win32 Debug"
# Name "parser - Win32 Alpha Debug"
# Name "parser - Win32 Alpha Release"
***************
*** 168,174 ****
SOURCE=..\Modules\parsermodule.c
! !IF "$(CFG)" == "parser - Win32 x86 Release"
! !ELSEIF "$(CFG)" == "parser - Win32 x86 Debug"
!ELSEIF "$(CFG)" == "parser - Win32 Alpha Debug"
--- 168,174 ----
SOURCE=..\Modules\parsermodule.c
! !IF "$(CFG)" == "parser - Win32 Release"
! !ELSEIF "$(CFG)" == "parser - Win32 Debug"
!ELSEIF "$(CFG)" == "parser - Win32 Alpha Debug"
Index: python.dsp
===================================================================
RCS file: /projects/cvsroot/python/dist/src/PCbuild/python.dsp,v
retrieving revision 1.7
retrieving revision 1.8
diff -C2 -r1.7 -r1.8
*** python.dsp 2000/01/20 21:31:41 1.7
--- python.dsp 2000/02/03 17:19:35 1.8
***************
*** 19,24 ****
!MESSAGE Possible choices for configuration are:
!MESSAGE
! !MESSAGE "python - Win32 x86 Release" (based on "Win32 (x86) Console Application")
! !MESSAGE "python - Win32 x86 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE "python - Win32 Alpha Debug" (based on "Win32 (ALPHA) Console Application")
!MESSAGE "python - Win32 Alpha Release" (based on "Win32 (ALPHA) Console Application")
--- 19,24 ----
!MESSAGE Possible choices for configuration are:
!MESSAGE
! !MESSAGE "python - Win32 Release" (based on "Win32 (x86) Console Application")
! !MESSAGE "python - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE "python - Win32 Alpha Debug" (based on "Win32 (ALPHA) Console Application")
!MESSAGE "python - Win32 Alpha Release" (based on "Win32 (ALPHA) Console Application")
***************
*** 30,34 ****
# PROP Scc_LocalPath ".."
! !IF "$(CFG)" == "python - Win32 x86 Release"
# PROP BASE Use_MFC 0
--- 30,34 ----
# PROP Scc_LocalPath ".."
! !IF "$(CFG)" == "python - Win32 Release"
# PROP BASE Use_MFC 0
***************
*** 56,60 ****
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /libpath:"Release"
! !ELSEIF "$(CFG)" == "python - Win32 x86 Debug"
# PROP BASE Use_MFC 0
--- 56,60 ----
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /libpath:"Release"
! !ELSEIF "$(CFG)" == "python - Win32 Debug"
# PROP BASE Use_MFC 0
***************
*** 140,145 ****
# Begin Target
! # Name "python - Win32 x86 Release"
! # Name "python - Win32 x86 Debug"
# Name "python - Win32 Alpha Debug"
# Name "python - Win32 Alpha Release"
--- 140,145 ----
# Begin Target
! # Name "python - Win32 Release"
! # Name "python - Win32 Debug"
# Name "python - Win32 Alpha Debug"
# Name "python - Win32 Alpha Release"
***************
*** 152,158 ****
SOURCE=..\Modules\python.c
! !IF "$(CFG)" == "python - Win32 x86 Release"
! !ELSEIF "$(CFG)" == "python - Win32 x86 Debug"
!ELSEIF "$(CFG)" == "python - Win32 Alpha Debug"
--- 152,158 ----
SOURCE=..\Modules\python.c
! !IF "$(CFG)" == "python - Win32 Release"
! !ELSEIF "$(CFG)" == "python - Win32 Debug"
!ELSEIF "$(CFG)" == "python - Win32 Alpha Debug"
Index: python15.dsp
===================================================================
RCS file: /projects/cvsroot/python/dist/src/PCbuild/python15.dsp,v
retrieving revision 1.10
retrieving revision 1.11
diff -C2 -r1.10 -r1.11
*** python15.dsp 2000/01/20 21:31:41 1.10
--- python15.dsp 2000/02/03 17:19:35 1.11
***************
*** 19,24 ****
!MESSAGE Possible choices for configuration are:
!MESSAGE
! !MESSAGE "python15 - Win32 x86 Release" (based on "Win32 (x86) Dynamic-Link Library")
! !MESSAGE "python15 - Win32 x86 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "python15 - Win32 Alpha Debug" (based on "Win32 (ALPHA) Dynamic-Link Library")
!MESSAGE "python15 - Win32 Alpha Release" (based on "Win32 (ALPHA) Dynamic-Link Library")
--- 19,24 ----
!MESSAGE Possible choices for configuration are:
!MESSAGE
! !MESSAGE "python15 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
[...1694 lines suppressed...]
! !ELSEIF "$(CFG)" == "python15 - Win32 Debug"
!ELSEIF "$(CFG)" == "python15 - Win32 Alpha Debug"
***************
*** 1637,1643 ****
SOURCE=..\Modules\yuvconvert.c
! !IF "$(CFG)" == "python15 - Win32 x86 Release"
! !ELSEIF "$(CFG)" == "python15 - Win32 x86 Debug"
!ELSEIF "$(CFG)" == "python15 - Win32 Alpha Debug"
--- 1637,1643 ----
SOURCE=..\Modules\yuvconvert.c
! !IF "$(CFG)" == "python15 - Win32 Release"
! !ELSEIF "$(CFG)" == "python15 - Win32 Debug"
!ELSEIF "$(CFG)" == "python15 - Win32 Alpha Debug"
Index: pythonw.dsp
===================================================================
RCS file: /projects/cvsroot/python/dist/src/PCbuild/pythonw.dsp,v
retrieving revision 1.6
retrieving revision 1.7
diff -C2 -r1.6 -r1.7
*** pythonw.dsp 2000/01/20 21:31:41 1.6
--- pythonw.dsp 2000/02/03 17:19:35 1.7
***************
*** 19,24 ****
!MESSAGE Possible choices for configuration are:
!MESSAGE
! !MESSAGE "pythonw - Win32 x86 Release" (based on "Win32 (x86) Application")
! !MESSAGE "pythonw - Win32 x86 Debug" (based on "Win32 (x86) Application")
!MESSAGE "pythonw - Win32 Alpha Debug" (based on "Win32 (ALPHA) Application")
!MESSAGE "pythonw - Win32 Alpha Release" (based on "Win32 (ALPHA) Application")
--- 19,24 ----
!MESSAGE Possible choices for configuration are:
!MESSAGE
! !MESSAGE "pythonw - Win32 Release" (based on "Win32 (x86) Application")
! !MESSAGE "pythonw - Win32 Debug" (based on "Win32 (x86) Application")
!MESSAGE "pythonw - Win32 Alpha Debug" (based on "Win32 (ALPHA) Application")
!MESSAGE "pythonw - Win32 Alpha Release" (based on "Win32 (ALPHA) Application")
***************
*** 30,34 ****
# PROP Scc_LocalPath "..\pc"
! !IF "$(CFG)" == "pythonw - Win32 x86 Release"
# PROP BASE Use_MFC 0
--- 30,34 ----
# PROP Scc_LocalPath "..\pc"
! !IF "$(CFG)" == "pythonw - Win32 Release"
# PROP BASE Use_MFC 0
***************
*** 60,64 ****
# SUBTRACT LINK32 /pdb:none
! !ELSEIF "$(CFG)" == "pythonw - Win32 x86 Debug"
# PROP BASE Use_MFC 0
--- 60,64 ----
# SUBTRACT LINK32 /pdb:none
! !ELSEIF "$(CFG)" == "pythonw - Win32 Debug"
# PROP BASE Use_MFC 0
***************
*** 158,163 ****
# Begin Target
! # Name "pythonw - Win32 x86 Release"
! # Name "pythonw - Win32 x86 Debug"
# Name "pythonw - Win32 Alpha Debug"
# Name "pythonw - Win32 Alpha Release"
--- 158,163 ----
# Begin Target
! # Name "pythonw - Win32 Release"
! # Name "pythonw - Win32 Debug"
# Name "pythonw - Win32 Alpha Debug"
# Name "pythonw - Win32 Alpha Release"
***************
*** 170,176 ****
SOURCE=..\PC\WinMain.c
! !IF "$(CFG)" == "pythonw - Win32 x86 Release"
! !ELSEIF "$(CFG)" == "pythonw - Win32 x86 Debug"
!ELSEIF "$(CFG)" == "pythonw - Win32 Alpha Debug"
--- 170,176 ----
SOURCE=..\PC\WinMain.c
! !IF "$(CFG)" == "pythonw - Win32 Release"
! !ELSEIF "$(CFG)" == "pythonw - Win32 Debug"
!ELSEIF "$(CFG)" == "pythonw - Win32 Alpha Debug"
Index: zlib.dsp
===================================================================
RCS file: /projects/cvsroot/python/dist/src/PCbuild/zlib.dsp,v
retrieving revision 1.7
retrieving revision 1.8
diff -C2 -r1.7 -r1.8
*** zlib.dsp 2000/01/20 21:31:41 1.7
--- zlib.dsp 2000/02/03 17:19:35 1.8
***************
*** 5,9 ****
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
! CFG=zlib - Win32 x86 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
--- 5,9 ----
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
! CFG=zlib - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
***************
*** 14,23 ****
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
! !MESSAGE NMAKE /f "zlib.mak" CFG="zlib - Win32 x86 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
! !MESSAGE "zlib - Win32 x86 Release" (based on "Win32 (x86) Dynamic-Link Library")
! !MESSAGE "zlib - Win32 x86 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
--- 14,23 ----
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
! !MESSAGE NMAKE /f "zlib.mak" CFG="zlib - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
! !MESSAGE "zlib - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
! !MESSAGE "zlib - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
***************
*** 30,34 ****
RSC=rc.exe
! !IF "$(CFG)" == "zlib - Win32 x86 Release"
# PROP BASE Use_MFC 0
--- 30,34 ----
RSC=rc.exe
! !IF "$(CFG)" == "zlib - Win32 Release"
# PROP BASE Use_MFC 0
***************
*** 58,62 ****
# SUBTRACT LINK32 /pdb:none
! !ELSEIF "$(CFG)" == "zlib - Win32 x86 Debug"
# PROP BASE Use_MFC 0
--- 58,62 ----
# SUBTRACT LINK32 /pdb:none
! !ELSEIF "$(CFG)" == "zlib - Win32 Debug"
# PROP BASE Use_MFC 0
***************
*** 90,95 ****
# Begin Target
! # Name "zlib - Win32 x86 Release"
! # Name "zlib - Win32 x86 Debug"
# Begin Source File
--- 90,95 ----
# Begin Target
! # Name "zlib - Win32 Release"
! # Name "zlib - Win32 Debug"
# Begin Source File
From fdrake@weyr.cnri.reston.va.us Thu Feb 3 18:23:38 2000
From: fdrake@weyr.cnri.reston.va.us (Fred L. Drake)
Date: Thu, 3 Feb 2000 13:23:38 -0500 (EST)
Subject: [Python-checkins] CVS: python/dist/src/Doc/api api.tex,1.56.2.7,1.56.2.8
Message-ID: <200002031823.NAA03107@weyr.cnri.reston.va.us>
Update of /projects/cvsroot/python/dist/src/Doc/api
In directory weyr:/home/fdrake/projects/python/Doc-152p1/api
Modified Files:
Tag: release152p1-patches
api.tex
Log Message:
PySequence_In() is replaced by PySequence_Contains().
Index: api.tex
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Doc/api/api.tex,v
retrieving revision 1.56.2.7
retrieving revision 1.56.2.8
diff -C2 -r1.56.2.7 -r1.56.2.8
*** api.tex 2000/01/17 14:30:04 1.56.2.7
--- api.tex 2000/02/03 18:23:34 1.56.2.8
***************
*** 1552,1556 ****
\end{cfuncdesc}
! \begin{cfuncdesc}{int}{PySequence_In}{PyObject *o, PyObject *value}
Determine if \var{o} contains \var{value}. If an item in \var{o} is
equal to \var{value}, return \code{1}, otherwise return \code{0}. On
--- 1552,1556 ----
\end{cfuncdesc}
! \begin{cfuncdesc}{int}{PySequence_Contains}{PyObject *o, PyObject *value}
Determine if \var{o} contains \var{value}. If an item in \var{o} is
equal to \var{value}, return \code{1}, otherwise return \code{0}. On
From guido@cnri.reston.va.us Fri Feb 4 15:10:40 2000
From: guido@cnri.reston.va.us (Guido van Rossum)
Date: Fri, 4 Feb 2000 10:10:40 -0500 (EST)
Subject: [Python-checkins] CVS: python/dist/src/Lib dospath.py,1.10,1.11 filecmp.py,1.2,1.3 fpformat.py,1.6,1.7 gopherlib.py,1.5,1.6 gzip.py,1.15,1.16 htmlentitydefs.py,1.4,1.5 imghdr.py,1.8,1.9 keyword.py,1.7,1.8 linecache.py,1.4,1.5 macpath.py,1.20,1.21 mailcap.py,1.4,1.5 mhlib.py,1.18,1.19 mimetools.py,1.15,1.16 mimify.py,1.13,1.14 multifile.py,1.8,1.9 mutex.py,1.5,1.6 netrc.py,1.3,1.4 nntplib.py,1.16,1.17 nturl2path.py,1.4,1.5 os.py,1.28,1.29 pdb.py,1.40,1.41 pickle.py,1.35,1.36 pipes.py,1.4,1.5 popen2.py,1.8,1.9 posixfile.py,1.12,1.13 posixpath.py,1.26,1.27 profile.py,1.21,1.22 pstats.py,1.6,1.7 pty.py,1.2,1.3 py_compile.py,1.14,1.15
Message-ID: <200002041510.KAA09691@eric.cnri.reston.va.us>
Update of /projects/cvsroot/python/dist/src/Lib
In directory eric:/projects/python/develop/guido/src/Lib
Modified Files:
dospath.py filecmp.py fpformat.py gopherlib.py gzip.py
htmlentitydefs.py imghdr.py keyword.py linecache.py macpath.py
mailcap.py mhlib.py mimetools.py mimify.py multifile.py
mutex.py netrc.py nntplib.py nturl2path.py os.py pdb.py
pickle.py pipes.py popen2.py posixfile.py posixpath.py
profile.py pstats.py pty.py py_compile.py
Log Message:
More trivial comment -> docstring transformations by Ka-Ping Yee,
who writes:
Here is batch 2, as a big collection of CVS context diffs.
Along with moving comments into docstrings, i've added a
couple of missing docstrings and attempted to make sure more
module docstrings begin with a one-line summary.
I did not add docstrings to the methods in profile.py for
fear of upsetting any careful optimizations there, though
i did move class documentation into class docstrings.
The convention i'm using is to leave credits/version/copyright
type of stuff in # comments, and move the rest of the descriptive
stuff about module usage into module docstrings. Hope this is
okay.
Index: dospath.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/dospath.py,v
retrieving revision 1.10
retrieving revision 1.11
diff -C2 -r1.10 -r1.11
*** dospath.py 1999/03/19 21:05:12 1.10
--- dospath.py 2000/02/04 15:10:32 1.11
***************
*** 1,3 ****
! # Module 'dospath' -- common operations on DOS pathnames
import os
--- 1,3 ----
! """Module 'dospath' -- common operations on DOS pathnames"""
import os
***************
*** 6,63 ****
- # Normalize the case of a pathname.
- # On MS-DOS it maps the pathname to lowercase, turns slashes into
- # backslashes.
- # Other normalizations (such as optimizing '../' away) are not allowed
- # (this is done by normpath).
- # Previously, this version mapped invalid consecutive characters to a
- # single '_', but this has been removed. This functionality should
- # possibly be added as a new function.
-
def normcase(s):
! return string.lower(string.replace(s, "/", "\\"))
- # Return wheter a path is absolute.
- # Trivial in Posix, harder on the Mac or MS-DOS.
- # For DOS it is absolute if it starts with a slash or backslash (current
- # volume), or if a pathname after the volume letter and colon starts with
- # a slash or backslash.
def isabs(s):
! s = splitdrive(s)[1]
! return s != '' and s[:1] in '/\\'
- # Join two (or more) paths.
def join(a, *p):
! path = a
! for b in p:
! if isabs(b):
! path = b
! elif path == '' or path[-1:] in '/\\':
! path = path + b
! else:
! path = path + os.sep + b
! return path
- # Split a path in a drive specification (a drive letter followed by a
- # colon) and the path specification.
- # It is always true that drivespec + pathspec == p
def splitdrive(p):
! if p[1:2] == ':':
! return p[0:2], p[2:]
! return '', p
!
- # Split a path in head (everything up to the last '/') and tail (the
- # rest). After the trailing '/' is stripped, the invariant
- # join(head, tail) == p holds.
- # The resulting head won't end in '/' unless it is the root.
def split(p):
d, p = splitdrive(p)
# set i to index beyond p's last slash
--- 6,63 ----
def normcase(s):
! """Normalize the case of a pathname.
! On MS-DOS it maps the pathname to lowercase, turns slashes into
! backslashes.
! Other normalizations (such as optimizing '../' away) are not allowed
! (this is done by normpath).
! Previously, this version mapped invalid consecutive characters to a
! single '_', but this has been removed. This functionality should
! possibly be added as a new function."""
+ return string.lower(string.replace(s, "/", "\\"))
def isabs(s):
! """Return whether a path is absolute.
! Trivial in Posix, harder on the Mac or MS-DOS.
! For DOS it is absolute if it starts with a slash or backslash (current
! volume), or if a pathname after the volume letter and colon starts with
! a slash or backslash."""
+ s = splitdrive(s)[1]
+ return s != '' and s[:1] in '/\\'
def join(a, *p):
! """Join two (or more) paths."""
+ path = a
+ for b in p:
+ if isabs(b):
+ path = b
+ elif path == '' or path[-1:] in '/\\':
+ path = path + b
+ else:
+ path = path + os.sep + b
+ return path
def splitdrive(p):
! """Split a path into a drive specification (a drive letter followed
! by a colon) and path specification.
! It is always true that drivespec + pathspec == p."""
!
! if p[1:2] == ':':
! return p[0:2], p[2:]
! return '', p
def split(p):
+ """Split a path into head (everything up to the last '/') and tail
+ (the rest). After the trailing '/' is stripped, the invariant
+ join(head, tail) == p holds.
+ The resulting head won't end in '/' unless it is the root."""
+
d, p = splitdrive(p)
# set i to index beyond p's last slash
***************
*** 74,118 ****
- # Split a path in root and extension.
- # The extension is everything starting at the first dot in the last
- # pathname component; the root is everything before that.
- # It is always true that root + ext == p.
-
def splitext(p):
! root, ext = '', ''
! for c in p:
! if c in '/\\':
! root, ext = root + ext + c, ''
! elif c == '.' or ext:
! ext = ext + c
! else:
! root = root + c
! return root, ext
!
- # Return the tail (basename) part of a path.
def basename(p):
! return split(p)[1]
- # Return the head (dirname) part of a path.
def dirname(p):
! return split(p)[0]
- # Return the longest prefix of all list elements.
def commonprefix(m):
! if not m: return ''
! prefix = m[0]
! for item in m:
! for i in range(len(prefix)):
! if prefix[:i+1] <> item[:i+1]:
! prefix = prefix[:i]
! if i == 0: return ''
! break
! return prefix
--- 74,118 ----
def splitext(p):
! """Split a path into root and extension.
! The extension is everything starting at the first dot in the last
! pathname component; the root is everything before that.
! It is always true that root + ext == p."""
!
! root, ext = '', ''
! for c in p:
! if c in '/\\':
! root, ext = root + ext + c, ''
! elif c == '.' or ext:
! ext = ext + c
! else:
! root = root + c
! return root, ext
def basename(p):
! """Return the tail (basename) part of a path."""
+ return split(p)[1]
def dirname(p):
! """Return the head (dirname) part of a path."""
+ return split(p)[0]
def commonprefix(m):
! """Return the longest prefix of all list elements."""
!
! if not m: return ''
! prefix = m[0]
! for item in m:
! for i in range(len(prefix)):
! if prefix[:i+1] <> item[:i+1]:
! prefix = prefix[:i]
! if i == 0: return ''
! break
! return prefix
***************
*** 135,332 ****
- # Is a path a symbolic link?
- # This will always return false on systems where posix.lstat doesn't exist.
-
def islink(path):
! return 0
- # Does a path exist?
- # This is false for dangling symbolic links.
def exists(path):
! try:
! st = os.stat(path)
! except os.error:
! return 0
! return 1
- # Is a path a dos directory?
- # This follows symbolic links, so both islink() and isdir() can be true
- # for the same path.
def isdir(path):
! try:
! st = os.stat(path)
! except os.error:
! return 0
! return stat.S_ISDIR(st[stat.ST_MODE])
- # Is a path a regular file?
- # This follows symbolic links, so both islink() and isdir() can be true
- # for the same path.
def isfile(path):
! try:
! st = os.stat(path)
! except os.error:
! return 0
! return stat.S_ISREG(st[stat.ST_MODE])
- # Is a path a mount point?
- # XXX This degenerates in: 'is this the root?' on DOS
def ismount(path):
! return isabs(splitdrive(path)[1])
- # Directory tree walk.
- # For each directory under top (including top itself, but excluding
- # '.' and '..'), func(arg, dirname, filenames) is called, where
- # dirname is the name of the directory and filenames is the list
- # files files (and subdirectories etc.) in the directory.
- # The func may modify the filenames list, to implement a filter,
- # or to impose a different order of visiting.
def walk(top, func, arg):
! try:
! names = os.listdir(top)
! except os.error:
! return
! func(arg, top, names)
! exceptions = ('.', '..')
! for name in names:
! if name not in exceptions:
! name = join(top, name)
! if isdir(name):
! walk(name, func, arg)
!
!
! # Expand paths beginning with '~' or '~user'.
! # '~' means $HOME; '~user' means that user's home directory.
! # If the path doesn't begin with '~', or if the user or $HOME is unknown,
! # the path is returned unchanged (leaving error reporting to whatever
! # function is called with the expanded path as argument).
! # See also module 'glob' for expansion of *, ? and [...] in pathnames.
! # (A function should also be defined to do full *sh-style environment
! # variable expansion.)
def expanduser(path):
! if path[:1] <> '~':
! return path
! i, n = 1, len(path)
! while i < n and path[i] not in '/\\':
! i = i+1
! if i == 1:
! if not os.environ.has_key('HOME'):
! return path
! userhome = os.environ['HOME']
! else:
! return path
! return userhome + path[i:]
!
!
! # Expand paths containing shell variable substitutions.
! # The following rules apply:
! # - no expansion within single quotes
! # - no escape character, except for '$$' which is translated into '$'
! # - ${varname} is accepted.
! # - varnames can be made out of letters, digits and the character '_'
! # XXX With COMMAND.COM you can use any characters in a variable name,
! # XXX except '^|<>='.
varchars = string.letters + string.digits + '_-'
def expandvars(path):
! if '$' not in path:
! return path
! res = ''
! index = 0
! pathlen = len(path)
! while index < pathlen:
! c = path[index]
! if c == '\'': # no expansion within single quotes
! path = path[index + 1:]
! pathlen = len(path)
! try:
! index = string.index(path, '\'')
! res = res + '\'' + path[:index + 1]
! except string.index_error:
! res = res + path
! index = pathlen -1
! elif c == '$': # variable or '$$'
! if path[index + 1:index + 2] == '$':
! res = res + c
! index = index + 1
! elif path[index + 1:index + 2] == '{':
! path = path[index+2:]
! pathlen = len(path)
! try:
! index = string.index(path, '}')
! var = path[:index]
! if os.environ.has_key(var):
! res = res + os.environ[var]
! except string.index_error:
! res = res + path
! index = pathlen - 1
! else:
! var = ''
! index = index + 1
! c = path[index:index + 1]
! while c != '' and c in varchars:
! var = var + c
! index = index + 1
! c = path[index:index + 1]
! if os.environ.has_key(var):
! res = res + os.environ[var]
! if c != '':
! res = res + c
! else:
! res = res + c
! index = index + 1
! return res
- # Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A/B.
- # Also, components of the path are silently truncated to 8+3 notation.
-
def normpath(path):
! path = string.replace(path, "/", "\\")
! prefix, path = splitdrive(path)
! while path[:1] == os.sep:
! prefix = prefix + os.sep
! path = path[1:]
! comps = string.splitfields(path, os.sep)
! i = 0
! while i < len(comps):
! if comps[i] == '.':
! del comps[i]
! elif comps[i] == '..' and i > 0 and \
! comps[i-1] not in ('', '..'):
! del comps[i-1:i+1]
! i = i-1
! elif comps[i] == '' and i > 0 and comps[i-1] <> '':
! del comps[i]
! elif '.' in comps[i]:
! comp = string.splitfields(comps[i], '.')
! comps[i] = comp[0][:8] + '.' + comp[1][:3]
! i = i+1
! elif len(comps[i]) > 8:
! comps[i] = comps[i][:8]
! i = i+1
! else:
! i = i+1
! # If the path is now empty, substitute '.'
! if not prefix and not comps:
! comps.append('.')
! return prefix + string.joinfields(comps, os.sep)
- # Return an absolute path.
def abspath(path):
if not isabs(path):
path = join(os.getcwd(), path)
--- 135,328 ----
def islink(path):
! """Is a path a symbolic link?
! This will always return false on systems where posix.lstat doesn't exist."""
+ return 0
def exists(path):
! """Does a path exist?
! This is false for dangling symbolic links."""
+ try:
+ st = os.stat(path)
+ except os.error:
+ return 0
+ return 1
def isdir(path):
! """Is a path a dos directory?"""
+ try:
+ st = os.stat(path)
+ except os.error:
+ return 0
+ return stat.S_ISDIR(st[stat.ST_MODE])
def isfile(path):
! """Is a path a regular file?"""
+ try:
+ st = os.stat(path)
+ except os.error:
+ return 0
+ return stat.S_ISREG(st[stat.ST_MODE])
def ismount(path):
! """Is a path a mount point?"""
! # XXX This degenerates in: 'is this the root?' on DOS
+ return isabs(splitdrive(path)[1])
def walk(top, func, arg):
! """Directory tree walk.
! For each directory under top (including top itself, but excluding
! '.' and '..'), func(arg, dirname, filenames) is called, where
! dirname is the name of the directory and filenames is the list
! files files (and subdirectories etc.) in the directory.
! The func may modify the filenames list, to implement a filter,
! or to impose a different order of visiting."""
!
! try:
! names = os.listdir(top)
! except os.error:
! return
! func(arg, top, names)
! exceptions = ('.', '..')
! for name in names:
! if name not in exceptions:
! name = join(top, name)
! if isdir(name):
! walk(name, func, arg)
!
def expanduser(path):
! """Expand paths beginning with '~' or '~user'.
! '~' means $HOME; '~user' means that user's home directory.
! If the path doesn't begin with '~', or if the user or $HOME is unknown,
! the path is returned unchanged (leaving error reporting to whatever
! function is called with the expanded path as argument).
! See also module 'glob' for expansion of *, ? and [...] in pathnames.
! (A function should also be defined to do full *sh-style environment
! variable expansion.)"""
!
! if path[:1] <> '~':
! return path
! i, n = 1, len(path)
! while i < n and path[i] not in '/\\':
! i = i+1
! if i == 1:
! if not os.environ.has_key('HOME'):
! return path
! userhome = os.environ['HOME']
! else:
! return path
! return userhome + path[i:]
!
varchars = string.letters + string.digits + '_-'
def expandvars(path):
! """Expand paths containing shell variable substitutions.
! The following rules apply:
! - no expansion within single quotes
! - no escape character, except for '$$' which is translated into '$'
! - ${varname} is accepted.
! - varnames can be made out of letters, digits and the character '_'"""
! # XXX With COMMAND.COM you can use any characters in a variable name,
! # XXX except '^|<>='.
!
! if '$' not in path:
! return path
! res = ''
! index = 0
! pathlen = len(path)
! while index < pathlen:
! c = path[index]
! if c == '\'': # no expansion within single quotes
! path = path[index + 1:]
! pathlen = len(path)
! try:
! index = string.index(path, '\'')
! res = res + '\'' + path[:index + 1]
! except string.index_error:
! res = res + path
! index = pathlen -1
! elif c == '$': # variable or '$$'
! if path[index + 1:index + 2] == '$':
! res = res + c
! index = index + 1
! elif path[index + 1:index + 2] == '{':
! path = path[index+2:]
! pathlen = len(path)
! try:
! index = string.index(path, '}')
! var = path[:index]
! if os.environ.has_key(var):
! res = res + os.environ[var]
! except string.index_error:
! res = res + path
! index = pathlen - 1
! else:
! var = ''
! index = index + 1
! c = path[index:index + 1]
! while c != '' and c in varchars:
! var = var + c
! index = index + 1
! c = path[index:index + 1]
! if os.environ.has_key(var):
! res = res + os.environ[var]
! if c != '':
! res = res + c
! else:
! res = res + c
! index = index + 1
! return res
def normpath(path):
! """Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A/B.
! Also, components of the path are silently truncated to 8+3 notation."""
!
! path = string.replace(path, "/", "\\")
! prefix, path = splitdrive(path)
! while path[:1] == os.sep:
! prefix = prefix + os.sep
! path = path[1:]
! comps = string.splitfields(path, os.sep)
! i = 0
! while i < len(comps):
! if comps[i] == '.':
! del comps[i]
! elif comps[i] == '..' and i > 0 and \
! comps[i-1] not in ('', '..'):
! del comps[i-1:i+1]
! i = i-1
! elif comps[i] == '' and i > 0 and comps[i-1] <> '':
! del comps[i]
! elif '.' in comps[i]:
! comp = string.splitfields(comps[i], '.')
! comps[i] = comp[0][:8] + '.' + comp[1][:3]
! i = i+1
! elif len(comps[i]) > 8:
! comps[i] = comps[i][:8]
! i = i+1
! else:
! i = i+1
! # If the path is now empty, substitute '.'
! if not prefix and not comps:
! comps.append('.')
! return prefix + string.joinfields(comps, os.sep)
def abspath(path):
+ """Return an absolute path."""
if not isabs(path):
path = join(os.getcwd(), path)
Index: filecmp.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/filecmp.py,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -r1.2 -r1.3
*** filecmp.py 2000/02/03 00:41:22 1.2
--- filecmp.py 2000/02/04 15:10:32 1.3
***************
*** 1,318 ****
! """Utilities for comparing files and directories.
! Classes:
! dircmp
- Functions:
- cmp(f1, f2, shallow=1, use_statcache=0) -> int
- cmpfiles(a, b, common) -> ([], [], [])
-
- """
-
- import os
- import stat
- import statcache
-
_cache = {}
BUFSIZE=8*1024
! def cmp(f1, f2, shallow=1,use_statcache=0):
! """Compare two files.
! Arguments:
! f1 -- First file name
! f2 -- Second file name
! shallow -- Just check stat signature (do not read the files).
! defaults to 1.
! use_statcache -- Do not stat() each file directly: go through
! the statcache module for more efficiency.
! Return value:
! integer -- 1 if the files are the same, 0 otherwise.
! This function uses a cache for past comparisons and the results,
! with a cache invalidation mechanism relying on stale signatures.
! Of course, if 'use_statcache' is true, this mechanism is defeated,
! and the cache will never grow stale.
! """
! stat_function = (os.stat, statcache.stat)[use_statcache]
! s1, s2 = _sig(stat_function(f1)), _sig(stat_function(f2))
! if s1[0]!=stat.S_IFREG or s2[0]!=stat.S_IFREG: return 0
! if shallow and s1 == s2: return 1
! if s1[1]!=s2[1]: return 0
! result = _cache.get((f1, f2))
! if result and (s1, s2)==result[:2]:
! return result[2]
! outcome = _do_cmp(f1, f2)
! _cache[f1, f2] = s1, s2, outcome
! return outcome
def _sig(st):
! return (stat.S_IFMT(st[stat.ST_MODE]),
! st[stat.ST_SIZE],
! st[stat.ST_MTIME])
def _do_cmp(f1, f2):
! bufsize = BUFSIZE
! fp1 , fp2 = open(f1, 'rb'), open(f2, 'rb')
! while 1:
! b1, b2 = fp1.read(bufsize), fp2.read(bufsize)
! if b1!=b2: return 0
! if not b1: return 1
!
! # Directory comparison class.
! #
! class dircmp:
! """A class that manages the comparison of 2 directories.
!
! dircmp(a,b,ignore=None,hide=None)
! A and B are directories.
! IGNORE is a list of names to ignore,
! defaults to ['RCS', 'CVS', 'tags'].
! HIDE is a list of names to hide,
! defaults to [os.curdir, os.pardir].
!
! High level usage:
! x = dircmp(dir1, dir2)
! x.report() -> prints a report on the differences between dir1 and dir2
! or
! x.report_partial_closure() -> prints report on differences between dir1
! and dir2, and reports on common immediate subdirectories.
! x.report_full_closure() -> like report_partial_closure,
! but fully recursive.
!
! Attributes:
! left_list, right_list: The files in dir1 and dir2,
! filtered by hide and ignore.
! common: a list of names in both dir1 and dir2.
! left_only, right_only: names only in dir1, dir2.
! common_dirs: subdirectories in both dir1 and dir2.
! common_files: files in both dir1 and dir2.
! common_funny: names in both dir1 and dir2 where the type differs between
! dir1 and dir2, or the name is not stat-able.
! same_files: list of identical files.
! diff_files: list of filenames which differ.
! funny_files: list of files which could not be compared.
! subdirs: a dictionary of dircmp objects, keyed by names in common_dirs.
! """
!
! def __init__(self, a, b, ignore=None, hide=None): # Initialize
! self.left = a
! self.right = b
! if hide is None:
! self.hide = [os.curdir, os.pardir] # Names never to be shown
! else:
! self.hide = hide
! if ignore is None:
! self.ignore = ['RCS', 'CVS', 'tags'] # Names ignored in comparison
! else:
! self.ignore = ignore
!
! def phase0(self): # Compare everything except common subdirectories
! self.left_list = _filter(os.listdir(self.left),
! self.hide+self.ignore)
! self.right_list = _filter(os.listdir(self.right),
! self.hide+self.ignore)
! self.left_list.sort()
! self.right_list.sort()
!
! __p4_attrs = ('subdirs',)
! __p3_attrs = ('same_files', 'diff_files', 'funny_files')
! __p2_attrs = ('common_dirs', 'common_files', 'common_funny')
! __p1_attrs = ('common', 'left_only', 'right_only')
! __p0_attrs = ('left_list', 'right_list')
!
! def __getattr__(self, attr):
! if attr in self.__p4_attrs:
! self.phase4()
! elif attr in self.__p3_attrs:
! self.phase3()
! elif attr in self.__p2_attrs:
! self.phase2()
! elif attr in self.__p1_attrs:
! self.phase1()
! elif attr in self.__p0_attrs:
! self.phase0()
! else:
! raise AttributeError, attr
! return getattr(self, attr)
!
! def phase1(self): # Compute common names
! a_only, b_only = [], []
! common = {}
! b = {}
! for fnm in self.right_list:
! b[fnm] = 1
! for x in self.left_list:
! if b.get(x, 0):
! common[x] = 1
! else:
! a_only.append(x)
! for x in self.right_list:
! if common.get(x, 0):
! pass
! else:
! b_only.append(x)
! self.common = common.keys()
! self.left_only = a_only
! self.right_only = b_only
!
! def phase2(self): # Distinguish files, directories, funnies
! self.common_dirs = []
! self.common_files = []
! self.common_funny = []
!
! for x in self.common:
! a_path = os.path.join(self.left, x)
! b_path = os.path.join(self.right, x)
!
! ok = 1
! try:
! a_stat = statcache.stat(a_path)
! except os.error, why:
! # print 'Can\'t stat', a_path, ':', why[1]
! ok = 0
! try:
! b_stat = statcache.stat(b_path)
! except os.error, why:
! # print 'Can\'t stat', b_path, ':', why[1]
! ok = 0
!
! if ok:
! a_type = stat.S_IFMT(a_stat[stat.ST_MODE])
! b_type = stat.S_IFMT(b_stat[stat.ST_MODE])
! if a_type <> b_type:
! self.common_funny.append(x)
! elif stat.S_ISDIR(a_type):
! self.common_dirs.append(x)
! elif stat.S_ISREG(a_type):
! self.common_files.append(x)
! else:
! self.common_funny.append(x)
! else:
! self.common_funny.append(x)
!
! def phase3(self): # Find out differences between common files
! xx = cmpfiles(self.left, self.right, self.common_files)
! self.same_files, self.diff_files, self.funny_files = xx
!
! def phase4(self): # Find out differences between common subdirectories
! # A new dircmp object is created for each common subdirectory,
! # these are stored in a dictionary indexed by filename.
! # The hide and ignore properties are inherited from the parent
! self.subdirs = {}
! for x in self.common_dirs:
! a_x = os.path.join(self.left, x)
! b_x = os.path.join(self.right, x)
! self.subdirs[x] = dircmp(a_x, b_x, self.ignore, self.hide)
!
! def phase4_closure(self): # Recursively call phase4() on subdirectories
! self.phase4()
! for x in self.subdirs.keys():
! self.subdirs[x].phase4_closure()
!
! def report(self): # Print a report on the differences between a and b
! # Output format is purposely lousy
! print 'diff', self.left, self.right
! if self.left_only:
! self.left_only.sort()
! print 'Only in', self.left, ':', self.left_only
! if self.right_only:
! self.right_only.sort()
! print 'Only in', self.right, ':', self.right_only
! if self.same_files:
! self.same_files.sort()
! print 'Identical files :', self.same_files
! if self.diff_files:
! self.diff_files.sort()
! print 'Differing files :', self.diff_files
! if self.funny_files:
! self.funny_files.sort()
! print 'Trouble with common files :', self.funny_files
! if self.common_dirs:
! self.common_dirs.sort()
! print 'Common subdirectories :', self.common_dirs
! if self.common_funny:
! self.common_funny.sort()
! print 'Common funny cases :', self.common_funny
!
! def report_partial_closure(self): # Print reports on self and on subdirs
! self.report()
! for x in self.subdirs.keys():
! print
! self.subdirs[x].report()
!
! def report_full_closure(self): # Report on self and subdirs recursively
! self.report()
! for x in self.subdirs.keys():
! print
! self.subdirs[x].report_full_closure()
!
!
! # Compare common files in two directories.
! # Return:
! # - files that compare equal
! # - files that compare different
! # - funny cases (can't stat etc.)
! #
! def cmpfiles(a, b, common):
! """Compare common files in two directories.
!
! cmpfiles(a,b,common)
! A and B are directory names
! COMMON is a list of file names
! returns a tuple of three lists:
! files that compare equal
! files that are different
! filenames that aren't regular files."""
!
! res = ([], [], [])
! for x in common:
! res[_cmp(os.path.join(a, x), os.path.join(b, x))].append(x)
! return res
!
!
! # Compare two files.
! # Return:
! # 0 for equal
! # 1 for different
! # 2 for funny cases (can't stat, etc.)
! #
! def _cmp(a, b):
! try:
! return not abs(cmp(a, b))
! except os.error:
! return 2
!
!
! # Return a copy with items that occur in skip removed.
! #
! def _filter(list, skip):
! result = []
! for item in list:
! if item not in skip: result.append(item)
! return result
!
!
! # Demonstration and testing.
! #
! def demo():
! import sys
! import getopt
! options, args = getopt.getopt(sys.argv[1:], 'r')
! if len(args) <> 2: raise getopt.error, 'need exactly two args'
! dd = dircmp(args[0], args[1])
! if ('-r', '') in options:
! dd.report_full_closure()
! else:
! dd.report()
!
! if __name__ == '__main__':
! demo()
--- 1,57 ----
! """Compare files."""
! import os, stat, statcache
_cache = {}
BUFSIZE=8*1024
! def cmp(f1, f2, shallow=1,use_statcache=0):
! """Compare two files.
! Arguments:
! f1 -- First file name
! f2 -- Second file name
! shallow -- Just check stat signature (do not read the files).
! defaults to 1.
! use_statcache -- Do not stat() each file directly: go through
! the statcache module for more efficiency.
! Return value:
! integer -- 1 if the files are the same, 0 otherwise.
! This function uses a cache for past comparisons and the results,
! with a cache invalidation mechanism relying on stale signatures.
! Of course, if 'use_statcache' is true, this mechanism is defeated,
! and the cache will never grow stale.
! """
! stat_function = (os.stat, statcache.stat)[use_statcache]
! s1, s2 = _sig(stat_function(f1)), _sig(stat_function(f2))
! if s1[0]!=stat.S_IFREG or s2[0]!=stat.S_IFREG: return 0
! if shallow and s1 == s2: return 1
! if s1[1]!=s2[1]: return 0
! result = _cache.get((f1, f2))
! if result and (s1, s2)==result[:2]:
! return result[2]
! outcome = _do_cmp(f1, f2)
! _cache[f1, f2] = s1, s2, outcome
! return outcome
def _sig(st):
! return (stat.S_IFMT(st[stat.ST_MODE]),
! st[stat.ST_SIZE],
! st[stat.ST_MTIME])
def _do_cmp(f1, f2):
! bufsize = BUFSIZE
! fp1 , fp2 = open(f1, 'rb'), open(f2, 'rb')
! while 1:
! b1, b2 = fp1.read(bufsize), fp2.read(bufsize)
! if b1!=b2: return 0
! if not b1: return 1
Index: fpformat.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/fpformat.py,v
retrieving revision 1.6
retrieving revision 1.7
diff -C2 -r1.6 -r1.7
*** fpformat.py 2000/02/02 15:10:13 1.6
--- fpformat.py 2000/02/04 15:10:32 1.7
***************
*** 23,141 ****
try:
! class NotANumber(ValueError):
! pass
except TypeError:
! NotANumber = 'fpformat.NotANumber'
- # Return (sign, intpart, fraction, expo) or raise an exception:
- # sign is '+' or '-'
- # intpart is 0 or more digits beginning with a nonzero
- # fraction is 0 or more digits
- # expo is an integer
def extract(s):
! res = decoder.match(s)
! if res is None: raise NotANumber, s
! sign, intpart, fraction, exppart = res.group(1,2,3,4)
! if sign == '+': sign = ''
! if fraction: fraction = fraction[1:]
! if exppart: expo = int(exppart[1:])
! else: expo = 0
! return sign, intpart, fraction, expo
- # Remove the exponent by changing intpart and fraction
def unexpo(intpart, fraction, expo):
! if expo > 0: # Move the point left
! f = len(fraction)
! intpart, fraction = intpart + fraction[:expo], fraction[expo:]
! if expo > f:
! intpart = intpart + '0'*(expo-f)
! elif expo < 0: # Move the point right
! i = len(intpart)
! intpart, fraction = intpart[:expo], intpart[expo:] + fraction
! if expo < -i:
! fraction = '0'*(-expo-i) + fraction
! return intpart, fraction
- # Round or extend the fraction to size digs
def roundfrac(intpart, fraction, digs):
! f = len(fraction)
! if f <= digs:
! return intpart, fraction + '0'*(digs-f)
! i = len(intpart)
! if i+digs < 0:
! return '0'*-digs, ''
! total = intpart + fraction
! nextdigit = total[i+digs]
! if nextdigit >= '5': # Hard case: increment last digit, may have carry!
! n = i + digs - 1
! while n >= 0:
! if total[n] != '9': break
! n = n-1
! else:
! total = '0' + total
! i = i+1
! n = 0
! total = total[:n] + chr(ord(total[n]) + 1) + '0'*(len(total)-n-1)
! intpart, fraction = total[:i], total[i:]
! if digs >= 0:
! return intpart, fraction[:digs]
! else:
! return intpart[:digs] + '0'*-digs, ''
!
! # Format x as [-]ddd.ddd with 'digs' digits after the point
! # and at least one digit before.
! # If digs <= 0, the point is suppressed.
def fix(x, digs):
! if type(x) != type(''): x = `x`
! try:
! sign, intpart, fraction, expo = extract(x)
! except NotANumber:
! return x
! intpart, fraction = unexpo(intpart, fraction, expo)
! intpart, fraction = roundfrac(intpart, fraction, digs)
! while intpart and intpart[0] == '0': intpart = intpart[1:]
! if intpart == '': intpart = '0'
! if digs > 0: return sign + intpart + '.' + fraction
! else: return sign + intpart
!
! # Format x as [-]d.dddE[+-]ddd with 'digs' digits after the point
! # and exactly one digit before.
! # If digs is <= 0, one digit is kept and the point is suppressed.
def sci(x, digs):
! if type(x) != type(''): x = `x`
! sign, intpart, fraction, expo = extract(x)
! if not intpart:
! while fraction and fraction[0] == '0':
! fraction = fraction[1:]
! expo = expo - 1
! if fraction:
! intpart, fraction = fraction[0], fraction[1:]
! expo = expo - 1
! else:
! intpart = '0'
! else:
! expo = expo + len(intpart) - 1
! intpart, fraction = intpart[0], intpart[1:] + fraction
! digs = max(0, digs)
! intpart, fraction = roundfrac(intpart, fraction, digs)
! if len(intpart) > 1:
! intpart, fraction, expo = \
! intpart[0], intpart[1:] + fraction[:-1], \
! expo + len(intpart) - 1
! s = sign + intpart
! if digs > 0: s = s + '.' + fraction
! e = `abs(expo)`
! e = '0'*(3-len(e)) + e
! if expo < 0: e = '-' + e
! else: e = '+' + e
! return s + 'e' + e
- # Interactive test run
def test():
! try:
! while 1:
! x, digs = input('Enter (x, digs): ')
! print x, fix(x, digs), sci(x, digs)
! except (EOFError, KeyboardInterrupt):
! pass
--- 23,141 ----
try:
! class NotANumber(ValueError):
! pass
except TypeError:
! NotANumber = 'fpformat.NotANumber'
def extract(s):
! """Return (sign, intpart, fraction, expo) or raise an exception:
! sign is '+' or '-'
! intpart is 0 or more digits beginning with a nonzero
! fraction is 0 or more digits
! expo is an integer"""
! res = decoder.match(s)
! if res is None: raise NotANumber, s
! sign, intpart, fraction, exppart = res.group(1,2,3,4)
! if sign == '+': sign = ''
! if fraction: fraction = fraction[1:]
! if exppart: expo = int(exppart[1:])
! else: expo = 0
! return sign, intpart, fraction, expo
def unexpo(intpart, fraction, expo):
! """Remove the exponent by changing intpart and fraction."""
! if expo > 0: # Move the point left
! f = len(fraction)
! intpart, fraction = intpart + fraction[:expo], fraction[expo:]
! if expo > f:
! intpart = intpart + '0'*(expo-f)
! elif expo < 0: # Move the point right
! i = len(intpart)
! intpart, fraction = intpart[:expo], intpart[expo:] + fraction
! if expo < -i:
! fraction = '0'*(-expo-i) + fraction
! return intpart, fraction
def roundfrac(intpart, fraction, digs):
! """Round or extend the fraction to size digs."""
! f = len(fraction)
! if f <= digs:
! return intpart, fraction + '0'*(digs-f)
! i = len(intpart)
! if i+digs < 0:
! return '0'*-digs, ''
! total = intpart + fraction
! nextdigit = total[i+digs]
! if nextdigit >= '5': # Hard case: increment last digit, may have carry!
! n = i + digs - 1
! while n >= 0:
! if total[n] != '9': break
! n = n-1
! else:
! total = '0' + total
! i = i+1
! n = 0
! total = total[:n] + chr(ord(total[n]) + 1) + '0'*(len(total)-n-1)
! intpart, fraction = total[:i], total[i:]
! if digs >= 0:
! return intpart, fraction[:digs]
! else:
! return intpart[:digs] + '0'*-digs, ''
!
def fix(x, digs):
! """Format x as [-]ddd.ddd with 'digs' digits after the point
! and at least one digit before.
! If digs <= 0, the point is suppressed."""
! if type(x) != type(''): x = `x`
! try:
! sign, intpart, fraction, expo = extract(x)
! except NotANumber:
! return x
! intpart, fraction = unexpo(intpart, fraction, expo)
! intpart, fraction = roundfrac(intpart, fraction, digs)
! while intpart and intpart[0] == '0': intpart = intpart[1:]
! if intpart == '': intpart = '0'
! if digs > 0: return sign + intpart + '.' + fraction
! else: return sign + intpart
!
def sci(x, digs):
! """Format x as [-]d.dddE[+-]ddd with 'digs' digits after the point
! and exactly one digit before.
! If digs is <= 0, one digit is kept and the point is suppressed."""
! if type(x) != type(''): x = `x`
! sign, intpart, fraction, expo = extract(x)
! if not intpart:
! while fraction and fraction[0] == '0':
! fraction = fraction[1:]
! expo = expo - 1
! if fraction:
! intpart, fraction = fraction[0], fraction[1:]
! expo = expo - 1
! else:
! intpart = '0'
! else:
! expo = expo + len(intpart) - 1
! intpart, fraction = intpart[0], intpart[1:] + fraction
! digs = max(0, digs)
! intpart, fraction = roundfrac(intpart, fraction, digs)
! if len(intpart) > 1:
! intpart, fraction, expo = \
! intpart[0], intpart[1:] + fraction[:-1], \
! expo + len(intpart) - 1
! s = sign + intpart
! if digs > 0: s = s + '.' + fraction
! e = `abs(expo)`
! e = '0'*(3-len(e)) + e
! if expo < 0: e = '-' + e
! else: e = '+' + e
! return s + 'e' + e
def test():
! """Interactive test run."""
! try:
! while 1:
! x, digs = input('Enter (x, digs): ')
! print x, fix(x, digs), sci(x, digs)
! except (EOFError, KeyboardInterrupt):
! pass
Index: gopherlib.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/gopherlib.py,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -r1.5 -r1.6
*** gopherlib.py 1998/03/26 20:43:41 1.5
--- gopherlib.py 2000/02/04 15:10:32 1.6
***************
*** 1,3 ****
! # Gopher protocol client interface
import string
--- 1,3 ----
! """Gopher protocol client interface."""
import string
***************
*** 30,35 ****
A_QUERY = 'q'
A_GIF = 'g'
! A_HTML = 'h' # HTML file
! A_WWW = 'w' # WWW address
A_PLUS_IMAGE = ':'
A_PLUS_MOVIE = ';'
--- 30,35 ----
A_QUERY = 'q'
A_GIF = 'g'
! A_HTML = 'h' # HTML file
! A_WWW = 'w' # WWW address
A_PLUS_IMAGE = ':'
A_PLUS_MOVIE = ';'
***************
*** 37,52 ****
- # Function mapping all file types to strings; unknown types become TYPE='x'
_names = dir()
_type_to_name_map = {}
def type_to_name(gtype):
! global _type_to_name_map
! if _type_to_name_map=={}:
! for name in _names:
! if name[:2] == 'A_':
! _type_to_name_map[eval(name)] = name[2:]
! if _type_to_name_map.has_key(gtype):
! return _type_to_name_map[gtype]
! return 'TYPE=' + `gtype`
# Names for characters and strings
--- 37,52 ----
_names = dir()
_type_to_name_map = {}
def type_to_name(gtype):
! """Map all file types to strings; unknown types become TYPE='x'."""
! global _type_to_name_map
! if _type_to_name_map=={}:
! for name in _names:
! if name[:2] == 'A_':
! _type_to_name_map[eval(name)] = name[2:]
! if _type_to_name_map.has_key(gtype):
! return _type_to_name_map[gtype]
! return 'TYPE=' + `gtype`
# Names for characters and strings
***************
*** 54,208 ****
TAB = '\t'
- # Send a selector to a given host and port, return a file with the reply
def send_selector(selector, host, port = 0):
! import socket
! import string
! if not port:
! i = string.find(host, ':')
! if i >= 0:
! host, port = host[:i], string.atoi(host[i+1:])
! if not port:
! port = DEF_PORT
! elif type(port) == type(''):
! port = string.atoi(port)
! s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
! s.connect(host, port)
! s.send(selector + CRLF)
! s.shutdown(1)
! return s.makefile('rb')
- # Send a selector and a query string
def send_query(selector, query, host, port = 0):
! return send_selector(selector + '\t' + query, host, port)
- # Takes a path as returned by urlparse and returns the appropriate selector
def path_to_selector(path):
! if path=="/":
! return "/"
! else:
! return path[2:] # Cuts initial slash and data type identifier
- # Takes a path as returned by urlparse and maps it to a string
- # See section 3.4 of RFC 1738 for details
def path_to_datatype_name(path):
! if path=="/":
! # No way to tell, although "INDEX" is likely
! return "TYPE='unknown'"
! else:
! return type_to_name(path[1])
# The following functions interpret the data returned by the gopher
# server according to the expected type, e.g. textfile or directory
- # Get a directory in the form of a list of entries
def get_directory(f):
! import string
! list = []
! while 1:
! line = f.readline()
! if not line:
! print '(Unexpected EOF from server)'
! break
! if line[-2:] == CRLF:
! line = line[:-2]
! elif line[-1:] in CRLF:
! line = line[:-1]
! if line == '.':
! break
! if not line:
! print '(Empty line from server)'
! continue
! gtype = line[0]
! parts = string.splitfields(line[1:], TAB)
! if len(parts) < 4:
! print '(Bad line from server:', `line`, ')'
! continue
! if len(parts) > 4:
! if parts[4:] != ['+']:
! print '(Extra info from server:',
! print parts[4:], ')'
! else:
! parts.append('')
! parts.insert(0, gtype)
! list.append(parts)
! return list
- # Get a text file as a list of lines, with trailing CRLF stripped
def get_textfile(f):
! list = []
! get_alt_textfile(f, list.append)
! return list
- # Get a text file and pass each line to a function, with trailing CRLF stripped
def get_alt_textfile(f, func):
! while 1:
! line = f.readline()
! if not line:
! print '(Unexpected EOF from server)'
! break
! if line[-2:] == CRLF:
! line = line[:-2]
! elif line[-1:] in CRLF:
! line = line[:-1]
! if line == '.':
! break
! if line[:2] == '..':
! line = line[1:]
! func(line)
- # Get a binary file as one solid data block
def get_binary(f):
! data = f.read()
! return data
- # Get a binary file and pass each block to a function
def get_alt_binary(f, func, blocksize):
! while 1:
! data = f.read(blocksize)
! if not data:
! break
! func(data)
- # Trivial test program
def test():
! import sys
! import getopt
! opts, args = getopt.getopt(sys.argv[1:], '')
! selector = DEF_SELECTOR
! type = selector[0]
! host = DEF_HOST
! port = DEF_PORT
! if args:
! host = args[0]
! args = args[1:]
! if args:
! type = args[0]
! args = args[1:]
! if len(type) > 1:
! type, selector = type[0], type
! else:
! selector = ''
! if args:
! selector = args[0]
! args = args[1:]
! query = ''
! if args:
! query = args[0]
! args = args[1:]
! if type == A_INDEX:
! f = send_query(selector, query, host)
! else:
! f = send_selector(selector, host)
! if type == A_TEXT:
! list = get_textfile(f)
! for item in list: print item
! elif type in (A_MENU, A_INDEX):
! list = get_directory(f)
! for item in list: print item
! else:
! data = get_binary(f)
! print 'binary data:', len(data), 'bytes:', `data[:100]`[:40]
# Run the test when run as script
if __name__ == '__main__':
! test()
--- 54,208 ----
TAB = '\t'
def send_selector(selector, host, port = 0):
! """Send a selector to a given host and port, return a file with the reply."""
! import socket
! import string
! if not port:
! i = string.find(host, ':')
! if i >= 0:
! host, port = host[:i], string.atoi(host[i+1:])
! if not port:
! port = DEF_PORT
! elif type(port) == type(''):
! port = string.atoi(port)
! s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
! s.connect(host, port)
! s.send(selector + CRLF)
! s.shutdown(1)
! return s.makefile('rb')
def send_query(selector, query, host, port = 0):
! """Send a selector and a query string."""
! return send_selector(selector + '\t' + query, host, port)
def path_to_selector(path):
! """Takes a path as returned by urlparse and returns the appropriate selector."""
! if path=="/":
! return "/"
! else:
! return path[2:] # Cuts initial slash and data type identifier
def path_to_datatype_name(path):
! """Takes a path as returned by urlparse and maps it to a string.
! See section 3.4 of RFC 1738 for details."""
! if path=="/":
! # No way to tell, although "INDEX" is likely
! return "TYPE='unknown'"
! else:
! return type_to_name(path[1])
# The following functions interpret the data returned by the gopher
# server according to the expected type, e.g. textfile or directory
def get_directory(f):
! """Get a directory in the form of a list of entries."""
! import string
! list = []
! while 1:
! line = f.readline()
! if not line:
! print '(Unexpected EOF from server)'
! break
! if line[-2:] == CRLF:
! line = line[:-2]
! elif line[-1:] in CRLF:
! line = line[:-1]
! if line == '.':
! break
! if not line:
! print '(Empty line from server)'
! continue
! gtype = line[0]
! parts = string.splitfields(line[1:], TAB)
! if len(parts) < 4:
! print '(Bad line from server:', `line`, ')'
! continue
! if len(parts) > 4:
! if parts[4:] != ['+']:
! print '(Extra info from server:',
! print parts[4:], ')'
! else:
! parts.append('')
! parts.insert(0, gtype)
! list.append(parts)
! return list
def get_textfile(f):
! """Get a text file as a list of lines, with trailing CRLF stripped."""
! list = []
! get_alt_textfile(f, list.append)
! return list
def get_alt_textfile(f, func):
! """Get a text file and pass each line to a function, with trailing CRLF stripped."""
! while 1:
! line = f.readline()
! if not line:
! print '(Unexpected EOF from server)'
! break
! if line[-2:] == CRLF:
! line = line[:-2]
! elif line[-1:] in CRLF:
! line = line[:-1]
! if line == '.':
! break
! if line[:2] == '..':
! line = line[1:]
! func(line)
def get_binary(f):
! """Get a binary file as one solid data block."""
! data = f.read()
! return data
def get_alt_binary(f, func, blocksize):
! """Get a binary file and pass each block to a function."""
! while 1:
! data = f.read(blocksize)
! if not data:
! break
! func(data)
def test():
! """Trivial test program."""
! import sys
! import getopt
! opts, args = getopt.getopt(sys.argv[1:], '')
! selector = DEF_SELECTOR
! type = selector[0]
! host = DEF_HOST
! port = DEF_PORT
! if args:
! host = args[0]
! args = args[1:]
! if args:
! type = args[0]
! args = args[1:]
! if len(type) > 1:
! type, selector = type[0], type
! else:
! selector = ''
! if args:
! selector = args[0]
! args = args[1:]
! query = ''
! if args:
! query = args[0]
! args = args[1:]
! if type == A_INDEX:
! f = send_query(selector, query, host)
! else:
! f = send_selector(selector, host)
! if type == A_TEXT:
! list = get_textfile(f)
! for item in list: print item
! elif type in (A_MENU, A_INDEX):
! list = get_directory(f)
! for item in list: print item
! else:
! data = get_binary(f)
! print 'binary data:', len(data), 'bytes:', `data[:100]`[:40]
# Run the test when run as script
if __name__ == '__main__':
! test()
Index: gzip.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/gzip.py,v
retrieving revision 1.15
retrieving revision 1.16
diff -C2 -r1.15 -r1.16
*** gzip.py 2000/02/02 16:51:06 1.15
--- gzip.py 2000/02/04 15:10:32 1.16
***************
*** 1,2 ****
--- 1,8 ----
+ """This module implements a function that reads and writes a gzipped file.
+ The user of the file doesn't have to worry about the compression,
+ but random access is not allowed."""
+
+ # based on Andrew Kuchling's minigzip.py distributed with the zlib module
+
import time
import string
***************
*** 4,13 ****
import struct
import __builtin__
-
- # implements a python function that reads and writes a gzipped file
- # the user of the file doesn't have to worry about the compression,
- # but random access is not allowed
-
- # based on Andrew Kuchling's minigzip.py distributed with the zlib module
FTEXT, FHCRC, FEXTRA, FNAME, FCOMMENT = 1, 2, 4, 8, 16
--- 10,13 ----
Index: htmlentitydefs.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/htmlentitydefs.py,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -r1.4 -r1.5
*** htmlentitydefs.py 1999/08/19 15:59:35 1.4
--- htmlentitydefs.py 2000/02/04 15:10:33 1.5
***************
*** 1,2 ****
--- 1,4 ----
+ """HTML character entity references."""
+
entitydefs = {
'AElig': '\306', # latin capital letter AE = latin capital ligature AE, U+00C6 ISOlat1
Index: imghdr.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/imghdr.py,v
retrieving revision 1.8
retrieving revision 1.9
diff -C2 -r1.8 -r1.9
*** imghdr.py 1997/10/08 15:22:32 1.8
--- imghdr.py 2000/02/04 15:10:33 1.9
***************
*** 1,3 ****
! # Recognizing image files based on their first few bytes.
--- 1,3 ----
! """Recognize image file formats based on their first few bytes."""
***************
*** 7,29 ****
def what(file, h=None):
! if h is None:
! if type(file) == type(''):
! f = open(file, 'rb')
! h = f.read(32)
! else:
! location = file.tell()
! h = file.read(32)
! file.seek(location)
! f = None
! else:
! f = None
! try:
! for tf in tests:
! res = tf(h, f)
! if res:
! return res
! finally:
! if f: f.close()
! return None
--- 7,29 ----
def what(file, h=None):
! if h is None:
! if type(file) == type(''):
! f = open(file, 'rb')
! h = f.read(32)
! else:
! location = file.tell()
! h = file.read(32)
! file.seek(location)
! f = None
! else:
! f = None
! try:
! for tf in tests:
! res = tf(h, f)
! if res:
! return res
! finally:
! if f: f.close()
! return None
***************
*** 35,113 ****
def test_rgb(h, f):
! # SGI image library
! if h[:2] == '\001\332':
! return 'rgb'
tests.append(test_rgb)
def test_gif(h, f):
! # GIF ('87 and '89 variants)
! if h[:6] in ('GIF87a', 'GIF89a'):
! return 'gif'
tests.append(test_gif)
def test_pbm(h, f):
! # PBM (portable bitmap)
! if len(h) >= 3 and \
! h[0] == 'P' and h[1] in '14' and h[2] in ' \t\n\r':
! return 'pbm'
tests.append(test_pbm)
def test_pgm(h, f):
! # PGM (portable graymap)
! if len(h) >= 3 and \
! h[0] == 'P' and h[1] in '25' and h[2] in ' \t\n\r':
! return 'pgm'
tests.append(test_pgm)
def test_ppm(h, f):
! # PPM (portable pixmap)
! if len(h) >= 3 and \
! h[0] == 'P' and h[1] in '36' and h[2] in ' \t\n\r':
! return 'ppm'
tests.append(test_ppm)
def test_tiff(h, f):
! # TIFF (can be in Motorola or Intel byte order)
! if h[:2] in ('MM', 'II'):
! return 'tiff'
tests.append(test_tiff)
def test_rast(h, f):
! # Sun raster file
! if h[:4] == '\x59\xA6\x6A\x95':
! return 'rast'
tests.append(test_rast)
def test_xbm(h, f):
! # X bitmap (X10 or X11)
! s = '#define '
! if h[:len(s)] == s:
! return 'xbm'
tests.append(test_xbm)
def test_jpeg(h, f):
! # JPEG data in JFIF format
! if h[6:10] == 'JFIF':
! return 'jpeg'
tests.append(test_jpeg)
def test_bmp(h, f):
! if h[:2] == 'BM':
! return 'bmp'
!
tests.append(test_bmp)
def test_png(h, f):
! if h[:8] == "\211PNG\r\n\032\n":
! return 'png'
tests.append(test_png)
--- 35,113 ----
def test_rgb(h, f):
! """SGI image library"""
! if h[:2] == '\001\332':
! return 'rgb'
tests.append(test_rgb)
def test_gif(h, f):
! """GIF ('87 and '89 variants)"""
! if h[:6] in ('GIF87a', 'GIF89a'):
! return 'gif'
tests.append(test_gif)
def test_pbm(h, f):
! """PBM (portable bitmap)"""
! if len(h) >= 3 and \
! h[0] == 'P' and h[1] in '14' and h[2] in ' \t\n\r':
! return 'pbm'
tests.append(test_pbm)
def test_pgm(h, f):
! """PGM (portable graymap)"""
! if len(h) >= 3 and \
! h[0] == 'P' and h[1] in '25' and h[2] in ' \t\n\r':
! return 'pgm'
tests.append(test_pgm)
def test_ppm(h, f):
! """PPM (portable pixmap)"""
! if len(h) >= 3 and \
! h[0] == 'P' and h[1] in '36' and h[2] in ' \t\n\r':
! return 'ppm'
tests.append(test_ppm)
def test_tiff(h, f):
! """TIFF (can be in Motorola or Intel byte order)"""
! if h[:2] in ('MM', 'II'):
! return 'tiff'
tests.append(test_tiff)
def test_rast(h, f):
! """Sun raster file"""
! if h[:4] == '\x59\xA6\x6A\x95':
! return 'rast'
tests.append(test_rast)
def test_xbm(h, f):
! """X bitmap (X10 or X11)"""
! s = '#define '
! if h[:len(s)] == s:
! return 'xbm'
tests.append(test_xbm)
def test_jpeg(h, f):
! """JPEG data in JFIF format"""
! if h[6:10] == 'JFIF':
! return 'jpeg'
tests.append(test_jpeg)
def test_bmp(h, f):
! if h[:2] == 'BM':
! return 'bmp'
!
tests.append(test_bmp)
def test_png(h, f):
! if h[:8] == "\211PNG\r\n\032\n":
! return 'png'
tests.append(test_png)
***************
*** 118,153 ****
def test():
! import sys
! recursive = 0
! if sys.argv[1:] and sys.argv[1] == '-r':
! del sys.argv[1:2]
! recursive = 1
! try:
! if sys.argv[1:]:
! testall(sys.argv[1:], recursive, 1)
! else:
! testall(['.'], recursive, 1)
! except KeyboardInterrupt:
! sys.stderr.write('\n[Interrupted]\n')
! sys.exit(1)
def testall(list, recursive, toplevel):
! import sys
! import os
! for filename in list:
! if os.path.isdir(filename):
! print filename + '/:',
! if recursive or toplevel:
! print 'recursing down:'
! import glob
! names = glob.glob(os.path.join(filename, '*'))
! testall(names, recursive, 0)
! else:
! print '*** directory (use -r) ***'
! else:
! print filename + ':',
! sys.stdout.flush()
! try:
! print what(filename)
! except IOError:
! print '*** not found ***'
--- 118,153 ----
def test():
! import sys
! recursive = 0
! if sys.argv[1:] and sys.argv[1] == '-r':
! del sys.argv[1:2]
! recursive = 1
! try:
! if sys.argv[1:]:
! testall(sys.argv[1:], recursive, 1)
! else:
! testall(['.'], recursive, 1)
! except KeyboardInterrupt:
! sys.stderr.write('\n[Interrupted]\n')
! sys.exit(1)
def testall(list, recursive, toplevel):
! import sys
! import os
! for filename in list:
! if os.path.isdir(filename):
! print filename + '/:',
! if recursive or toplevel:
! print 'recursing down:'
! import glob
! names = glob.glob(os.path.join(filename, '*'))
! testall(names, recursive, 0)
! else:
! print '*** directory (use -r) ***'
! else:
! print filename + ':',
! sys.stdout.flush()
! try:
! print what(filename)
! except IOError:
! print '*** not found ***'
Index: keyword.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/keyword.py,v
retrieving revision 1.7
retrieving revision 1.8
diff -C2 -r1.7 -r1.8
*** keyword.py 1998/03/26 21:12:18 1.7
--- keyword.py 2000/02/04 15:10:33 1.8
***************
*** 1,12 ****
#! /usr/bin/env python
! #
! # Keywords (from "graminit.c")
! #
! # This file is automatically generated; please don't muck it up!
! #
! # To update the symbols in this file, 'cd' to the top directory of
! # the python source tree after building the interpreter and run:
! #
! # python Lib/keyword.py
kwlist = [
--- 1,13 ----
#! /usr/bin/env python
!
! """Keywords (from "graminit.c")
!
! This file is automatically generated; please don't muck it up!
!
! To update the symbols in this file, 'cd' to the top directory of
! the python source tree after building the interpreter and run:
!
! python Lib/keyword.py
! """
kwlist = [
Index: linecache.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/linecache.py,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -r1.4 -r1.5
*** linecache.py 1995/08/10 19:32:22 1.4
--- linecache.py 2000/02/04 15:10:33 1.5
***************
*** 1,7 ****
! # Cache lines from files.
! # This is intended to read lines from modules imported -- hence if a filename
! # is not found, it will look down the module search path for a file by
! # that name.
import sys
import os
--- 1,9 ----
! """Cache lines from files.
+ This is intended to read lines from modules imported -- hence if a filename
+ is not found, it will look down the module search path for a file by
+ that name.
+ """
+
import sys
import os
***************
*** 9,17 ****
def getline(filename, lineno):
! lines = getlines(filename)
! if 1 <= lineno <= len(lines):
! return lines[lineno-1]
! else:
! return ''
--- 11,19 ----
def getline(filename, lineno):
! lines = getlines(filename)
! if 1 <= lineno <= len(lines):
! return lines[lineno-1]
! else:
! return ''
***************
*** 21,90 ****
- # Clear the cache entirely
-
def clearcache():
! global cache
! cache = {}
- # Get the lines for a file from the cache.
- # Update the cache if it doesn't contain an entry for this file already.
def getlines(filename):
! if cache.has_key(filename):
! return cache[filename][2]
! else:
! return updatecache(filename)
- # Discard cache entries that are out of date.
- # (This is not checked upon each call!)
def checkcache():
! for filename in cache.keys():
! size, mtime, lines, fullname = cache[filename]
! try:
! stat = os.stat(fullname)
! except os.error:
! del cache[filename]
! continue
! if size <> stat[ST_SIZE] or mtime <> stat[ST_MTIME]:
! del cache[filename]
- # Update a cache entry and return its list of lines.
- # If something's wrong, print a message, discard the cache entry,
- # and return an empty list.
def updatecache(filename):
! if cache.has_key(filename):
! del cache[filename]
! if not filename or filename[0] + filename[-1] == '<>':
! return []
! fullname = filename
! try:
! stat = os.stat(fullname)
! except os.error, msg:
! # Try looking through the module search path
! basename = os.path.split(filename)[1]
! for dirname in sys.path:
! fullname = os.path.join(dirname, basename)
! try:
! stat = os.stat(fullname)
! break
! except os.error:
! pass
! else:
! # No luck
! ## print '*** Cannot stat', filename, ':', msg
! return []
! try:
! fp = open(fullname, 'r')
! lines = fp.readlines()
! fp.close()
! except IOError, msg:
! ## print '*** Cannot open', fullname, ':', msg
! return []
! size, mtime = stat[ST_SIZE], stat[ST_MTIME]
! cache[filename] = size, mtime, lines, fullname
! return lines
--- 23,92 ----
def clearcache():
! """Clear the cache entirely."""
+ global cache
+ cache = {}
def getlines(filename):
! """Get the lines for a file from the cache.
! Update the cache if it doesn't contain an entry for this file already."""
+ if cache.has_key(filename):
+ return cache[filename][2]
+ else:
+ return updatecache(filename)
def checkcache():
! """Discard cache entries that are out of date.
! (This is not checked upon each call!)"""
+ for filename in cache.keys():
+ size, mtime, lines, fullname = cache[filename]
+ try:
+ stat = os.stat(fullname)
+ except os.error:
+ del cache[filename]
+ continue
+ if size <> stat[ST_SIZE] or mtime <> stat[ST_MTIME]:
+ del cache[filename]
def updatecache(filename):
! """Update a cache entry and return its list of lines.
! If something's wrong, print a message, discard the cache entry,
! and return an empty list."""
!
! if cache.has_key(filename):
! del cache[filename]
! if not filename or filename[0] + filename[-1] == '<>':
! return []
! fullname = filename
! try:
! stat = os.stat(fullname)
! except os.error, msg:
! # Try looking through the module search path
! basename = os.path.split(filename)[1]
! for dirname in sys.path:
! fullname = os.path.join(dirname, basename)
! try:
! stat = os.stat(fullname)
! break
! except os.error:
! pass
! else:
! # No luck
! ## print '*** Cannot stat', filename, ':', msg
! return []
! try:
! fp = open(fullname, 'r')
! lines = fp.readlines()
! fp.close()
! except IOError, msg:
! ## print '*** Cannot open', fullname, ':', msg
! return []
! size, mtime = stat[ST_SIZE], stat[ST_MTIME]
! cache[filename] = size, mtime, lines, fullname
! return lines
Index: macpath.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/macpath.py,v
retrieving revision 1.20
retrieving revision 1.21
diff -C2 -r1.20 -r1.21
*** macpath.py 1999/07/23 15:04:05 1.20
--- macpath.py 2000/02/04 15:10:33 1.21
***************
*** 1,3 ****
! # module 'macpath' -- pathname (or -related) operations for the Macintosh
import string
--- 1,3 ----
! """Pathname and path-related operations for the Macintosh."""
import string
***************
*** 11,85 ****
- # Return true if a path is absolute.
- # On the Mac, relative paths begin with a colon,
- # but as a special case, paths with no colons at all are also relative.
- # Anything else is absolute (the string up to the first colon is the
- # volume name).
-
def isabs(s):
! return ':' in s and s[0] <> ':'
def join(s, *p):
! path = s
! for t in p:
! if (not s) or isabs(t):
! path = t
! continue
! if t[:1] == ':':
! t = t[1:]
! if ':' not in path:
! path = ':' + path
! if path[-1:] <> ':':
! path = path + ':'
! path = path + t
! return path
!
!
! # Split a pathname in two parts: the directory leading up to the final bit,
! # and the basename (the filename, without colons, in that directory).
! # The result (s, t) is such that join(s, t) yields the original argument.
- def split(s):
- if ':' not in s: return '', s
- colon = 0
- for i in range(len(s)):
- if s[i] == ':': colon = i+1
- path, file = s[:colon-1], s[colon:]
- if path and not ':' in path:
- path = path + ':'
- return path, file
- # Split a path in root and extension.
- # The extension is everything starting at the last dot in the last
- # pathname component; the root is everything before that.
- # It is always true that root + ext == p.
def splitext(p):
! root, ext = '', ''
! for c in p:
! if c == ':':
! root, ext = root + ext + c, ''
! elif c == '.':
! if ext:
! root, ext = root + ext, c
! else:
! ext = c
! elif ext:
! ext = ext + c
! else:
! root = root + c
! return root, ext
!
!
! # Split a pathname into a drive specification and the rest of the
! # path. Useful on DOS/Windows/NT; on the Mac, the drive is always
! # empty (don't use the volume name -- it doesn't have the same
! # syntactic and semantic oddities as DOS drive letters, such as there
! # being a separate current directory per drive).
def splitdrive(p):
! return '', p
--- 11,85 ----
def isabs(s):
! """Return true if a path is absolute.
! On the Mac, relative paths begin with a colon,
! but as a special case, paths with no colons at all are also relative.
! Anything else is absolute (the string up to the first colon is the
! volume name)."""
!
! return ':' in s and s[0] <> ':'
def join(s, *p):
! path = s
! for t in p:
! if (not s) or isabs(t):
! path = t
! continue
! if t[:1] == ':':
! t = t[1:]
! if ':' not in path:
! path = ':' + path
! if path[-1:] <> ':':
! path = path + ':'
! path = path + t
! return path
+ def split(s):
+ """Split a pathname into two parts: the directory leading up to the final
+ bit, and the basename (the filename, without colons, in that directory).
+ The result (s, t) is such that join(s, t) yields the original argument."""
+
+ if ':' not in s: return '', s
+ colon = 0
+ for i in range(len(s)):
+ if s[i] == ':': colon = i+1
+ path, file = s[:colon-1], s[colon:]
+ if path and not ':' in path:
+ path = path + ':'
+ return path, file
def splitext(p):
! """Split a path into root and extension.
! The extension is everything starting at the last dot in the last
! pathname component; the root is everything before that.
! It is always true that root + ext == p."""
!
! root, ext = '', ''
! for c in p:
! if c == ':':
! root, ext = root + ext + c, ''
! elif c == '.':
! if ext:
! root, ext = root + ext, c
! else:
! ext = c
! elif ext:
! ext = ext + c
! else:
! root = root + c
! return root, ext
+
def splitdrive(p):
! """Split a pathname into a drive specification and the rest of the
! path. Useful on DOS/Windows/NT; on the Mac, the drive is always
! empty (don't use the volume name -- it doesn't have the same
! syntactic and semantic oddities as DOS drive letters, such as there
! being a separate current directory per drive)."""
!
! return '', p
***************
*** 90,101 ****
- # Return true if the pathname refers to an existing directory.
-
def isdir(s):
! try:
! st = os.stat(s)
! except os.error:
! return 0
! return S_ISDIR(st[ST_MODE])
--- 90,101 ----
def isdir(s):
! """Return true if the pathname refers to an existing directory."""
!
! try:
! st = os.stat(s)
! except os.error:
! return 0
! return S_ISDIR(st[ST_MODE])
***************
*** 118,220 ****
- # Return true if the pathname refers to a symbolic link.
- # (Always false on the Mac, until we understand Aliases.)
-
def islink(s):
! return 0
- # Return true if the pathname refers to an existing regular file.
def isfile(s):
! try:
! st = os.stat(s)
! except os.error:
! return 0
! return S_ISREG(st[ST_MODE])
- # Return true if the pathname refers to an existing file or directory.
def exists(s):
! try:
! st = os.stat(s)
! except os.error:
! return 0
! return 1
!
! #
! # dummy expandvars to retain interface-compatability with other
! # operating systems.
def expandvars(path):
! return path
- #
- # dummy expanduser to retain interface-compatability with other
- # operating systems.
- def expanduser(path):
- return path
! # Normalize a pathname: get rid of '::' sequences by backing up,
! # e.g., 'foo:bar::bletch' becomes 'foo:bletch'.
! # Raise the exception norm_error below if backing up is impossible,
! # e.g., for '::foo'.
! # XXX The Unix version doesn't raise an exception but simply
! # returns an unnormalized path. Should do so here too.
norm_error = 'macpath.norm_error: path cannot be normalized'
def normpath(s):
! import string
! if ':' not in s:
! return ':' + s
! f = string.splitfields(s, ':')
! pre = []
! post = []
! if not f[0]:
! pre = f[:1]
! f = f[1:]
! if not f[len(f)-1]:
! post = f[-1:]
! f = f[:-1]
! res = []
! for seg in f:
! if seg:
! res.append(seg)
! else:
! if not res: raise norm_error, 'path starts with ::'
! del res[len(res)-1]
! if not (pre or res):
! raise norm_error, 'path starts with volume::'
! if pre: res = pre + res
! if post: res = res + post
! s = res[0]
! for seg in res[1:]:
! s = s + ':' + seg
! return s
!
!
! # Directory tree walk.
! # For each directory under top (including top itself),
! # func(arg, dirname, filenames) is called, where
! # dirname is the name of the directory and filenames is the list
! # of files (and subdirectories etc.) in the directory.
! # The func may modify the filenames list, to implement a filter,
! # or to impose a different order of visiting.
def walk(top, func, arg):
! try:
! names = os.listdir(top)
! except os.error:
! return
! func(arg, top, names)
! for name in names:
! name = join(top, name)
! if isdir(name):
! walk(name, func, arg)
- # Return an absolute path.
def abspath(path):
if not isabs(path):
path = join(os.getcwd(), path)
--- 118,218 ----
def islink(s):
! """Return true if the pathname refers to a symbolic link.
! Always false on the Mac, until we understand Aliases.)"""
+ return 0
def isfile(s):
! """Return true if the pathname refers to an existing regular file."""
+ try:
+ st = os.stat(s)
+ except os.error:
+ return 0
+ return S_ISREG(st[ST_MODE])
def exists(s):
! """Return true if the pathname refers to an existing file or directory."""
!
! try:
! st = os.stat(s)
! except os.error:
! return 0
! return 1
!
!
def expandvars(path):
! """Dummy to retain interface-compatibility with other operating systems."""
! return path
! def expanduser(path):
! """Dummy to retain interface-compatibility with other operating systems."""
! return path
norm_error = 'macpath.norm_error: path cannot be normalized'
def normpath(s):
! """Normalize a pathname: get rid of '::' sequences by backing up,
! e.g., 'foo:bar::bletch' becomes 'foo:bletch'.
! Raise the exception norm_error below if backing up is impossible,
! e.g., for '::foo'."""
! # XXX The Unix version doesn't raise an exception but simply
! # returns an unnormalized path. Should do so here too.
!
! import string
! if ':' not in s:
! return ':' + s
! f = string.splitfields(s, ':')
! pre = []
! post = []
! if not f[0]:
! pre = f[:1]
! f = f[1:]
! if not f[len(f)-1]:
! post = f[-1:]
! f = f[:-1]
! res = []
! for seg in f:
! if seg:
! res.append(seg)
! else:
! if not res: raise norm_error, 'path starts with ::'
! del res[len(res)-1]
! if not (pre or res):
! raise norm_error, 'path starts with volume::'
! if pre: res = pre + res
! if post: res = res + post
! s = res[0]
! for seg in res[1:]:
! s = s + ':' + seg
! return s
!
def walk(top, func, arg):
! """Directory tree walk.
! For each directory under top (including top itself),
! func(arg, dirname, filenames) is called, where
! dirname is the name of the directory and filenames is the list
! of files (and subdirectories etc.) in the directory.
! The func may modify the filenames list, to implement a filter,
! or to impose a different order of visiting."""
!
! try:
! names = os.listdir(top)
! except os.error:
! return
! func(arg, top, names)
! for name in names:
! name = join(top, name)
! if isdir(name):
! walk(name, func, arg)
def abspath(path):
+ """Return an absolute path."""
if not isabs(path):
path = join(os.getcwd(), path)
Index: mailcap.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/mailcap.py,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -r1.4 -r1.5
*** mailcap.py 1998/03/26 21:12:26 1.4
--- mailcap.py 2000/02/04 15:10:33 1.5
***************
*** 10,15 ****
"""Return a dictionary containing the mailcap database.
! The dictionary maps a MIME type (in all lowercase,
! e.g. 'text/plain') to a list of corresponding mailcap entries.
"""
--- 10,18 ----
"""Return a dictionary containing the mailcap database.
! The dictionary maps a MIME type (in all lowercase, e.g. 'text/plain')
! to a list of dictionaries corresponding to mailcap entries. The list
! collects all the entries for that MIME type from all available mailcap
! files. Each dictionary contains key-value pairs for that MIME type,
! where the viewing command is stored with the key "view".
"""
***************
*** 49,52 ****
--- 52,63 ----
def readmailcapfile(fp):
+ """Read a mailcap file and return a dictionary keyed by MIME type.
+
+ Each MIME type is mapped to an entry consisting of a list of
+ dictionaries; the list will contain more than one such dictionary
+ if a given MIME type appears more than once in the mailcap file.
+ Each dictionary contains key-value pairs for that MIME type, where
+ the viewing command is stored with the key "view".
+ """
caps = {}
while 1:
***************
*** 79,82 ****
--- 90,98 ----
def parseline(line):
+ """Parse one entry in a mailcap file and return a dictionary.
+
+ The viewing command is stored as the value with the key "view",
+ and the rest of the fields produce key-value pairs in the dict.
+ """
fields = []
i, n = 0, len(line)
***************
*** 105,108 ****
--- 121,125 ----
def parsefield(line, i, n):
+ """Separate one key-value pair in a mailcap entry."""
start = i
while i < n:
Index: mhlib.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/mhlib.py,v
retrieving revision 1.18
retrieving revision 1.19
diff -C2 -r1.18 -r1.19
*** mhlib.py 1999/02/24 16:25:17 1.18
--- mhlib.py 2000/02/04 15:10:33 1.19
***************
*** 1,56 ****
! # MH interface -- purely object-oriented (well, almost)
! #
! # Executive summary:
! #
! # import mhlib
! #
! # mh = mhlib.MH() # use default mailbox directory and profile
! # mh = mhlib.MH(mailbox) # override mailbox location (default from profile)
! # mh = mhlib.MH(mailbox, profile) # override mailbox and profile
! #
! # mh.error(format, ...) # print error message -- can be overridden
! # s = mh.getprofile(key) # profile entry (None if not set)
! # path = mh.getpath() # mailbox pathname
! # name = mh.getcontext() # name of current folder
! # mh.setcontext(name) # set name of current folder
! #
! # list = mh.listfolders() # names of top-level folders
! # list = mh.listallfolders() # names of all folders, including subfolders
! # list = mh.listsubfolders(name) # direct subfolders of given folder
! # list = mh.listallsubfolders(name) # all subfolders of given folder
! #
! # mh.makefolder(name) # create new folder
! # mh.deletefolder(name) # delete folder -- must have no subfolders
! #
! # f = mh.openfolder(name) # new open folder object
! #
! # f.error(format, ...) # same as mh.error(format, ...)
! # path = f.getfullname() # folder's full pathname
! # path = f.getsequencesfilename() # full pathname of folder's sequences file
! # path = f.getmessagefilename(n) # full pathname of message n in folder
! #
! # list = f.listmessages() # list of messages in folder (as numbers)
! # n = f.getcurrent() # get current message
! # f.setcurrent(n) # set current message
! # list = f.parsesequence(seq) # parse msgs syntax into list of messages
! # n = f.getlast() # get last message (0 if no messagse)
! # f.setlast(n) # set last message (internal use only)
! #
! # dict = f.getsequences() # dictionary of sequences in folder {name: list}
! # f.putsequences(dict) # write sequences back to folder
! #
! # f.createmessage(n, fp) # add message from file f as number n
! # f.removemessages(list) # remove messages in list from folder
! # f.refilemessages(list, tofolder) # move messages in list to other folder
! # f.movemessage(n, tofolder, ton) # move one message to a given destination
! # f.copymessage(n, tofolder, ton) # copy one message to a given destination
! #
! # m = f.openmessage(n) # new open message object (costs a file descriptor)
! # m is a derived class of mimetools.Message(rfc822.Message), with:
! # s = m.getheadertext() # text of message's headers
! # s = m.getheadertext(pred) # text of message's headers, filtered by pred
! # s = m.getbodytext() # text of message's body, decoded
! # s = m.getbodytext(0) # text of message's body, not decoded
! #
# XXX To do, functionality:
# - annotate messages
--- 1,57 ----
! """MH interface -- purely object-oriented (well, almost)
!
! Executive summary:
!
! import mhlib
!
! mh = mhlib.MH() # use default mailbox directory and profile
! mh = mhlib.MH(mailbox) # override mailbox location (default from profile)
! mh = mhlib.MH(mailbox, profile) # override mailbox and profile
!
! mh.error(format, ...) # print error message -- can be overridden
! s = mh.getprofile(key) # profile entry (None if not set)
! path = mh.getpath() # mailbox pathname
! name = mh.getcontext() # name of current folder
! mh.setcontext(name) # set name of current folder
!
! list = mh.listfolders() # names of top-level folders
! list = mh.listallfolders() # names of all folders, including subfolders
! list = mh.listsubfolders(name) # direct subfolders of given folder
! list = mh.listallsubfolders(name) # all subfolders of given folder
!
! mh.makefolder(name) # create new folder
! mh.deletefolder(name) # delete folder -- must have no subfolders
!
! f = mh.openfolder(name) # new open folder object
!
! f.error(format, ...) # same as mh.error(format, ...)
! path = f.getfullname() # folder's full pathname
! path = f.getsequencesfilename() # full pathname of folder's sequences file
! path = f.getmessagefilename(n) # full pathname of message n in folder
!
! list = f.listmessages() # list of messages in folder (as numbers)
! n = f.getcurrent() # get current message
! f.setcurrent(n) # set current message
! list = f.parsesequence(seq) # parse msgs syntax into list of messages
! n = f.getlast() # get last message (0 if no messagse)
! f.setlast(n) # set last message (internal use only)
!
! dict = f.getsequences() # dictionary of sequences in folder {name: list}
! f.putsequences(dict) # write sequences back to folder
!
! f.createmessage(n, fp) # add message from file f as number n
! f.removemessages(list) # remove messages in list from folder
! f.refilemessages(list, tofolder) # move messages in list to other folder
! f.movemessage(n, tofolder, ton) # move one message to a given destination
! f.copymessage(n, tofolder, ton) # copy one message to a given destination
!
! m = f.openmessage(n) # new open message object (costs a file descriptor)
! m is a derived class of mimetools.Message(rfc822.Message), with:
! s = m.getheadertext() # text of message's headers
! s = m.getheadertext(pred) # text of message's headers, filtered by pred
! s = m.getbodytext() # text of message's body, decoded
! s = m.getbodytext(0) # text of message's body, not decoded
! """
!
# XXX To do, functionality:
# - annotate messages
***************
*** 88,101 ****
- # Class representing a particular collection of folders.
- # Optional constructor arguments are the pathname for the directory
- # containing the collection, and the MH profile to use.
- # If either is omitted or empty a default is used; the default
- # directory is taken from the MH profile if it is specified there.
-
class MH:
- # Constructor
def __init__(self, path = None, profile = None):
if not profile: profile = MH_PROFILE
self.profile = os.path.expanduser(profile)
--- 89,101 ----
class MH:
+ """Class representing a particular collection of folders.
+ Optional constructor arguments are the pathname for the directory
+ containing the collection, and the MH profile to use.
+ If either is omitted or empty a default is used; the default
+ directory is taken from the MH profile if it is specified there."""
def __init__(self, path = None, profile = None):
+ """Constructor."""
if not profile: profile = MH_PROFILE
self.profile = os.path.expanduser(profile)
***************
*** 108,129 ****
self.path = path
- # String representation
def __repr__(self):
return 'MH(%s, %s)' % (`self.path`, `self.profile`)
- # Routine to print an error. May be overridden by a derived class
def error(self, msg, *args):
sys.stderr.write('MH error: %s\n' % (msg % args))
- # Return a profile entry, None if not found
def getprofile(self, key):
return pickline(self.profile, key)
- # Return the path (the name of the collection's directory)
def getpath(self):
return self.path
- # Return the name of the current folder
def getcontext(self):
context = pickline(os.path.join(self.getpath(), 'context'),
'Current-Folder')
--- 108,129 ----
self.path = path
def __repr__(self):
+ """String representation."""
return 'MH(%s, %s)' % (`self.path`, `self.profile`)
def error(self, msg, *args):
+ """Routine to print an error. May be overridden by a derived class."""
sys.stderr.write('MH error: %s\n' % (msg % args))
def getprofile(self, key):
+ """Return a profile entry, None if not found."""
return pickline(self.profile, key)
def getpath(self):
+ """Return the path (the name of the collection's directory)."""
return self.path
def getcontext(self):
+ """Return the name of the current folder."""
context = pickline(os.path.join(self.getpath(), 'context'),
'Current-Folder')
***************
*** 131,136 ****
return context
- # Set the name of the current folder
def setcontext(self, context):
fn = os.path.join(self.getpath(), 'context')
f = open(fn, "w")
--- 131,136 ----
return context
def setcontext(self, context):
+ """Set the name of the current folder."""
fn = os.path.join(self.getpath(), 'context')
f = open(fn, "w")
***************
*** 138,143 ****
f.close()
- # Return the names of the top-level folders
def listfolders(self):
folders = []
path = self.getpath()
--- 138,143 ----
f.close()
def listfolders(self):
+ """Return the names of the top-level folders."""
folders = []
path = self.getpath()
***************
*** 149,155 ****
return folders
- # Return the names of the subfolders in a given folder
- # (prefixed with the given folder name)
def listsubfolders(self, name):
fullname = os.path.join(self.path, name)
# Get the link count so we can avoid listing folders
--- 149,155 ----
return folders
def listsubfolders(self, name):
+ """Return the names of the subfolders in a given folder
+ (prefixed with the given folder name)."""
fullname = os.path.join(self.path, name)
# Get the link count so we can avoid listing folders
***************
*** 174,183 ****
return subfolders
- # Return the names of all folders, including subfolders, recursively
def listallfolders(self):
return self.listallsubfolders('')
- # Return the names of subfolders in a given folder, recursively
def listallsubfolders(self, name):
fullname = os.path.join(self.path, name)
# Get the link count so we can avoid listing folders
--- 174,183 ----
return subfolders
def listallfolders(self):
+ """Return the names of all folders and subfolders, recursively."""
return self.listallsubfolders('')
def listallsubfolders(self, name):
+ """Return the names of subfolders in a given folder, recursively."""
fullname = os.path.join(self.path, name)
# Get the link count so we can avoid listing folders
***************
*** 207,217 ****
return subfolders
- # Return a new Folder object for the named folder
def openfolder(self, name):
return Folder(self, name)
- # Create a new folder. This raises os.error if the folder
- # cannot be created
def makefolder(self, name):
protect = pickline(self.profile, 'Folder-Protect')
if protect and isnumeric(protect):
--- 207,216 ----
return subfolders
def openfolder(self, name):
+ """Return a new Folder object for the named folder."""
return Folder(self, name)
def makefolder(self, name):
+ """Create a new folder (or raise os.error if it cannot be created)."""
protect = pickline(self.profile, 'Folder-Protect')
if protect and isnumeric(protect):
***************
*** 221,228 ****
os.mkdir(os.path.join(self.getpath(), name), mode)
- # Delete a folder. This removes files in the folder but not
- # subdirectories. If deleting the folder itself fails it
- # raises os.error
def deletefolder(self, name):
fullname = os.path.join(self.getpath(), name)
for subname in os.listdir(fullname):
--- 220,226 ----
os.mkdir(os.path.join(self.getpath(), name), mode)
def deletefolder(self, name):
+ """Delete a folder. This removes files in the folder but not
+ subdirectories. Raise os.error if deleting the folder itself fails."""
fullname = os.path.join(self.getpath(), name)
for subname in os.listdir(fullname):
***************
*** 236,241 ****
- # Class representing a particular folder
-
numericprog = re.compile('^[1-9][0-9]*$')
def isnumeric(str):
--- 234,237 ----
***************
*** 243,249 ****
class Folder:
- # Constructor
def __init__(self, mh, name):
self.mh = mh
self.name = name
--- 239,246 ----
class Folder:
+ """Class representing a particular folder."""
def __init__(self, mh, name):
+ """Constructor."""
self.mh = mh
self.name = name
***************
*** 251,285 ****
raise Error, 'no folder %s' % name
- # String representation
def __repr__(self):
return 'Folder(%s, %s)' % (`self.mh`, `self.name`)
- # Error message handler
def error(self, *args):
apply(self.mh.error, args)
- # Return the full pathname of the folder
def getfullname(self):
return os.path.join(self.mh.path, self.name)
- # Return the full pathname of the folder's sequences file
def getsequencesfilename(self):
return os.path.join(self.getfullname(), MH_SEQUENCES)
- # Return the full pathname of a message in the folder
def getmessagefilename(self, n):
return os.path.join(self.getfullname(), str(n))
- # Return list of direct subfolders
def listsubfolders(self):
return self.mh.listsubfolders(self.name)
- # Return list of all subfolders
def listallsubfolders(self):
return self.mh.listallsubfolders(self.name)
- # Return the list of messages currently present in the folder.
- # As a side effect, set self.last to the last message (or 0)
def listmessages(self):
messages = []
match = numericprog.match
--- 248,282 ----
raise Error, 'no folder %s' % name
def __repr__(self):
+ """String representation."""
return 'Folder(%s, %s)' % (`self.mh`, `self.name`)
def error(self, *args):
+ """Error message handler."""
apply(self.mh.error, args)
def getfullname(self):
+ """Return the full pathname of the folder."""
return os.path.join(self.mh.path, self.name)
def getsequencesfilename(self):
+ """Return the full pathname of the folder's sequences file."""
return os.path.join(self.getfullname(), MH_SEQUENCES)
def getmessagefilename(self, n):
+ """Return the full pathname of a message in the folder."""
return os.path.join(self.getfullname(), str(n))
def listsubfolders(self):
+ """Return list of direct subfolders."""
return self.mh.listsubfolders(self.name)
def listallsubfolders(self):
+ """Return list of all subfolders."""
return self.mh.listallsubfolders(self.name)
def listmessages(self):
+ """Return the list of messages currently present in the folder.
+ As a side effect, set self.last to the last message (or 0)."""
messages = []
match = numericprog.match
***************
*** 296,301 ****
return messages
- # Return the set of sequences for the folder
def getsequences(self):
sequences = {}
fullname = self.getsequencesfilename()
--- 293,298 ----
return messages
def getsequences(self):
+ """Return the set of sequences for the folder."""
sequences = {}
fullname = self.getsequencesfilename()
***************
*** 316,321 ****
return sequences
- # Write the set of sequences back to the folder
def putsequences(self, sequences):
fullname = self.getsequencesfilename()
f = None
--- 313,318 ----
return sequences
def putsequences(self, sequences):
+ """Write the set of sequences back to the folder."""
fullname = self.getsequencesfilename()
f = None
***************
*** 333,338 ****
f.close()
- # Return the current message. Raise KeyError when there is none
def getcurrent(self):
seqs = self.getsequences()
try:
--- 330,335 ----
f.close()
def getcurrent(self):
+ """Return the current message. Raise KeyError when there is none."""
seqs = self.getsequences()
try:
***************
*** 341,353 ****
raise Error, "no cur message"
- # Set the current message
def setcurrent(self, n):
updateline(self.getsequencesfilename(), 'cur', str(n), 0)
- # Parse an MH sequence specification into a message list.
- # Attempt to mimic mh-sequence(5) as close as possible.
- # Also attempt to mimic observed behavior regarding which
- # conditions cause which error messages
def parsesequence(self, seq):
# XXX Still not complete (see mh-format(5)).
# Missing are:
--- 338,350 ----
raise Error, "no cur message"
def setcurrent(self, n):
+ """Set the current message."""
updateline(self.getsequencesfilename(), 'cur', str(n), 0)
def parsesequence(self, seq):
+ """Parse an MH sequence specification into a message list.
+ Attempt to mimic mh-sequence(5) as close as possible.
+ Also attempt to mimic observed behavior regarding which
+ conditions cause which error messages."""
# XXX Still not complete (see mh-format(5)).
# Missing are:
***************
*** 429,434 ****
return [n]
- # Internal: parse a message number (or cur, first, etc.)
def _parseindex(self, seq, all):
if isnumeric(seq):
try:
--- 426,431 ----
return [n]
def _parseindex(self, seq, all):
+ """Internal: parse a message number (or cur, first, etc.)."""
if isnumeric(seq):
try:
***************
*** 460,469 ****
raise Error, None
- # Open a message -- returns a Message object
def openmessage(self, n):
return Message(self, n)
- # Remove one or more messages -- may raise os.error
def removemessages(self, list):
errors = []
deleted = []
--- 457,466 ----
raise Error, None
def openmessage(self, n):
+ """Open a message -- returns a Message object."""
return Message(self, n)
def removemessages(self, list):
+ """Remove one or more messages -- may raise os.error."""
errors = []
deleted = []
***************
*** 489,495 ****
raise os.error, ('multiple errors:', errors)
- # Refile one or more messages -- may raise os.error.
- # 'tofolder' is an open folder object
def refilemessages(self, list, tofolder, keepsequences=0):
errors = []
refiled = {}
--- 486,492 ----
raise os.error, ('multiple errors:', errors)
def refilemessages(self, list, tofolder, keepsequences=0):
+ """Refile one or more messages -- may raise os.error.
+ 'tofolder' is an open folder object."""
errors = []
refiled = {}
***************
*** 524,529 ****
raise os.error, ('multiple errors:', errors)
- # Helper for refilemessages() to copy sequences
def _copysequences(self, fromfolder, refileditems):
fromsequences = fromfolder.getsequences()
tosequences = self.getsequences()
--- 521,526 ----
raise os.error, ('multiple errors:', errors)
def _copysequences(self, fromfolder, refileditems):
+ """Helper for refilemessages() to copy sequences."""
fromsequences = fromfolder.getsequences()
tosequences = self.getsequences()
***************
*** 545,551 ****
self.putsequences(tosequences)
- # Move one message over a specific destination message,
- # which may or may not already exist.
def movemessage(self, n, tofolder, ton):
path = self.getmessagefilename(n)
# Open it to check that it exists
--- 542,548 ----
self.putsequences(tosequences)
def movemessage(self, n, tofolder, ton):
+ """Move one message over a specific destination message,
+ which may or may not already exist."""
path = self.getmessagefilename(n)
# Open it to check that it exists
***************
*** 577,583 ****
self.removefromallsequences([n])
- # Copy one message over a specific destination message,
- # which may or may not already exist.
def copymessage(self, n, tofolder, ton):
path = self.getmessagefilename(n)
# Open it to check that it exists
--- 574,580 ----
self.removefromallsequences([n])
def copymessage(self, n, tofolder, ton):
+ """Copy one message over a specific destination message,
+ which may or may not already exist."""
path = self.getmessagefilename(n)
# Open it to check that it exists
***************
*** 603,608 ****
pass
- # Create a message, with text from the open file txt.
def createmessage(self, n, txt):
path = self.getmessagefilename(n)
backuppath = self.getmessagefilename(',%d' % n)
--- 600,605 ----
pass
def createmessage(self, n, txt):
+ """Create a message, with text from the open file txt."""
path = self.getmessagefilename(n)
backuppath = self.getmessagefilename(',%d' % n)
***************
*** 629,635 ****
pass
- # Remove one or more messages from all sequeuces (including last)
- # -- but not from 'cur'!!!
def removefromallsequences(self, list):
if hasattr(self, 'last') and self.last in list:
del self.last
--- 626,632 ----
pass
def removefromallsequences(self, list):
+ """Remove one or more messages from all sequeuces (including last)
+ -- but not from 'cur'!!!"""
if hasattr(self, 'last') and self.last in list:
del self.last
***************
*** 648,659 ****
self.putsequences(sequences)
- # Return the last message number
def getlast(self):
if not hasattr(self, 'last'):
messages = self.listmessages()
return self.last
- # Set the last message number
def setlast(self, last):
if last is None:
if hasattr(self, 'last'):
--- 645,656 ----
self.putsequences(sequences)
def getlast(self):
+ """Return the last message number."""
if not hasattr(self, 'last'):
messages = self.listmessages()
return self.last
def setlast(self, last):
+ """Set the last message number."""
if last is None:
if hasattr(self, 'last'):
***************
*** 664,669 ****
class Message(mimetools.Message):
- # Constructor
def __init__(self, f, n, fp = None):
self.folder = f
self.number = n
--- 661,666 ----
class Message(mimetools.Message):
def __init__(self, f, n, fp = None):
+ """Constructor."""
self.folder = f
self.number = n
***************
*** 673,685 ****
mimetools.Message.__init__(self, fp)
- # String representation
def __repr__(self):
return 'Message(%s, %s)' % (repr(self.folder), self.number)
- # Return the message's header text as a string. If an
- # argument is specified, it is used as a filter predicate to
- # decide which headers to return (its argument is the header
- # name converted to lower case).
def getheadertext(self, pred = None):
if not pred:
return string.joinfields(self.headers, '')
--- 670,682 ----
mimetools.Message.__init__(self, fp)
def __repr__(self):
+ """String representation."""
return 'Message(%s, %s)' % (repr(self.folder), self.number)
def getheadertext(self, pred = None):
+ """Return the message's header text as a string. If an
+ argument is specified, it is used as a filter predicate to
+ decide which headers to return (its argument is the header
+ name converted to lower case)."""
if not pred:
return string.joinfields(self.headers, '')
***************
*** 694,702 ****
return string.joinfields(headers, '')
- # Return the message's body text as string. This undoes a
- # Content-Transfer-Encoding, but does not interpret other MIME
- # features (e.g. multipart messages). To suppress to
- # decoding, pass a 0 as argument
def getbodytext(self, decode = 1):
self.fp.seek(self.startofbody)
encoding = self.getencoding()
--- 691,699 ----
return string.joinfields(headers, '')
def getbodytext(self, decode = 1):
+ """Return the message's body text as string. This undoes a
+ Content-Transfer-Encoding, but does not interpret other MIME
+ features (e.g. multipart messages). To suppress decoding,
+ pass 0 as an argument."""
self.fp.seek(self.startofbody)
encoding = self.getencoding()
***************
*** 708,715 ****
return output.getvalue()
- # Only for multipart messages: return the message's body as a
- # list of SubMessage objects. Each submessage object behaves
- # (almost) as a Message object.
def getbodyparts(self):
if self.getmaintype() != 'multipart':
raise Error, 'Content-Type is not multipart/*'
--- 705,712 ----
return output.getvalue()
def getbodyparts(self):
+ """Only for multipart messages: return the message's body as a
+ list of SubMessage objects. Each submessage object behaves
+ (almost) as a Message object."""
if self.getmaintype() != 'multipart':
raise Error, 'Content-Type is not multipart/*'
***************
*** 728,733 ****
return parts
- # Return body, either a string or a list of messages
def getbody(self):
if self.getmaintype() == 'multipart':
return self.getbodyparts()
--- 725,730 ----
return parts
def getbody(self):
+ """Return body, either a string or a list of messages."""
if self.getmaintype() == 'multipart':
return self.getbodyparts()
***************
*** 738,743 ****
class SubMessage(Message):
- # Constructor
def __init__(self, f, n, fp):
Message.__init__(self, f, n, fp)
if self.getmaintype() == 'multipart':
--- 735,740 ----
class SubMessage(Message):
def __init__(self, f, n, fp):
+ """Constructor."""
Message.__init__(self, f, n, fp)
if self.getmaintype() == 'multipart':
***************
*** 748,753 ****
# XXX If this is big, should remember file pointers
- # String representation
def __repr__(self):
f, n, fp = self.folder, self.number, self.fp
return 'SubMessage(%s, %s, %s)' % (f, n, fp)
--- 745,750 ----
# XXX If this is big, should remember file pointers
def __repr__(self):
+ """String representation."""
f, n, fp = self.folder, self.number, self.fp
return 'SubMessage(%s, %s, %s)' % (f, n, fp)
***************
*** 767,792 ****
- # Class implementing sets of integers.
- #
- # This is an efficient representation for sets consisting of several
- # continuous ranges, e.g. 1-100,200-400,402-1000 is represented
- # internally as a list of three pairs: [(1,100), (200,400),
- # (402,1000)]. The internal representation is always kept normalized.
- #
- # The constructor has up to three arguments:
- # - the string used to initialize the set (default ''),
- # - the separator between ranges (default ',')
- # - the separator between begin and end of a range (default '-')
- # The separators must be strings (not regexprs) and should be different.
- #
- # The tostring() function yields a string that can be passed to another
- # IntSet constructor; __repr__() is a valid IntSet constructor itself.
- #
- # XXX The default begin/end separator means that negative numbers are
- # not supported very well.
- #
- # XXX There are currently no operations to remove set elements.
-
class IntSet:
def __init__(self, data = None, sep = ',', rng = '-'):
--- 764,789 ----
class IntSet:
+ """Class implementing sets of integers.
+
+ This is an efficient representation for sets consisting of several
+ continuous ranges, e.g. 1-100,200-400,402-1000 is represented
+ internally as a list of three pairs: [(1,100), (200,400),
+ (402,1000)]. The internal representation is always kept normalized.
+
+ The constructor has up to three arguments:
+ - the string used to initialize the set (default ''),
+ - the separator between ranges (default ',')
+ - the separator between begin and end of a range (default '-')
+ The separators must be strings (not regexprs) and should be different.
+
+ The tostring() function yields a string that can be passed to another
+ IntSet constructor; __repr__() is a valid IntSet constructor itself.
+ """
+
+ # XXX The default begin/end separator means that negative numbers are
+ # not supported very well.
+ #
+ # XXX There are currently no operations to remove set elements.
def __init__(self, data = None, sep = ',', rng = '-'):
Index: mimetools.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/mimetools.py,v
retrieving revision 1.15
retrieving revision 1.16
diff -C2 -r1.15 -r1.16
*** mimetools.py 1998/05/20 17:05:35 1.15
--- mimetools.py 2000/02/04 15:10:33 1.16
***************
*** 1,3 ****
! # Various tools used by MIME-reading or MIME-writing programs.
--- 1,3 ----
! """Various tools used by MIME-reading or MIME-writing programs."""
***************
*** 8,15 ****
- # A derived class of rfc822.Message that knows about MIME headers and
- # contains some hooks for decoding encoded and multipart messages.
-
class Message(rfc822.Message):
def __init__(self, fp, seekable = 1):
--- 8,14 ----
class Message(rfc822.Message):
+ """A derived class of rfc822.Message that knows about MIME headers and
+ contains some hooks for decoding encoded and multipart messages."""
def __init__(self, fp, seekable = 1):
***************
*** 97,111 ****
- # Return a random string usable as a multipart boundary.
- # The method used is so that it is *very* unlikely that the same
- # string of characters will every occur again in the Universe,
- # so the caller needn't check the data it is packing for the
- # occurrence of the boundary.
- #
- # The boundary contains dots so you have to quote it in the header.
-
_prefix = None
def choose_boundary():
global _prefix
import time
--- 96,110 ----
_prefix = None
def choose_boundary():
+ """Return a random string usable as a multipart boundary.
+ The method used is so that it is *very* unlikely that the same
+ string of characters will every occur again in the Universe,
+ so the caller needn't check the data it is packing for the
+ occurrence of the boundary.
+
+ The boundary contains dots so you have to quote it in the header."""
+
global _prefix
import time
***************
*** 132,135 ****
--- 131,135 ----
def decode(input, output, encoding):
+ """Decode common content-transfer-encodings (base64, quopri, uuencode)."""
if encoding == 'base64':
import base64
***************
*** 148,151 ****
--- 148,152 ----
def encode(input, output, encoding):
+ """Encode common content-transfer-encodings (base64, quopri, uuencode)."""
if encoding == 'base64':
import base64
Index: mimify.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/mimify.py,v
retrieving revision 1.13
retrieving revision 1.14
diff -C2 -r1.13 -r1.14
*** mimify.py 1998/08/07 15:26:56 1.13
--- mimify.py 2000/02/04 15:10:33 1.14
***************
*** 3,7 ****
'''Mimification and unmimification of mail messages.
! decode quoted-printable parts of a mail message or encode using
quoted-printable.
--- 3,7 ----
'''Mimification and unmimification of mail messages.
! Decode quoted-printable parts of a mail message or encode using
quoted-printable.
***************
*** 40,46 ****
class File:
! '''A simple fake file object that knows about limited
! read-ahead and boundaries.
! The only supported method is readline().'''
def __init__(self, file, boundary):
--- 40,45 ----
class File:
! """A simple fake file object that knows about limited read-ahead and
! boundaries. The only supported method is readline()."""
def __init__(self, file, boundary):
***************
*** 88,92 ****
def mime_decode(line):
! '''Decode a single line of quoted-printable text to 8bit.'''
newline = ''
pos = 0
--- 87,91 ----
def mime_decode(line):
! """Decode a single line of quoted-printable text to 8bit."""
newline = ''
pos = 0
***************
*** 101,105 ****
def mime_decode_header(line):
! '''Decode a header line to 8bit.'''
newline = ''
pos = 0
--- 100,104 ----
def mime_decode_header(line):
! """Decode a header line to 8bit."""
newline = ''
pos = 0
***************
*** 116,120 ****
def unmimify_part(ifile, ofile, decode_base64 = 0):
! '''Convert a quoted-printable part of a MIME mail message to 8bit.'''
multipart = None
quoted_printable = 0
--- 115,119 ----
def unmimify_part(ifile, ofile, decode_base64 = 0):
! """Convert a quoted-printable part of a MIME mail message to 8bit."""
multipart = None
quoted_printable = 0
***************
*** 201,205 ****
def unmimify(infile, outfile, decode_base64 = 0):
! '''Convert quoted-printable parts of a MIME mail message to 8bit.'''
if type(infile) == type(''):
ifile = open(infile)
--- 200,204 ----
def unmimify(infile, outfile, decode_base64 = 0):
! """Convert quoted-printable parts of a MIME mail message to 8bit."""
if type(infile) == type(''):
ifile = open(infile)
***************
*** 222,227 ****
def mime_encode(line, header):
! '''Code a single line as quoted-printable.
! If header is set, quote some extra characters.'''
if header:
reg = mime_header_char
--- 221,226 ----
def mime_encode(line, header):
! """Code a single line as quoted-printable.
! If header is set, quote some extra characters."""
if header:
reg = mime_header_char
***************
*** 256,260 ****
def mime_encode_header(line):
! '''Code a single header line as quoted-printable.'''
newline = ''
pos = 0
--- 255,259 ----
def mime_encode_header(line):
! """Code a single header line as quoted-printable."""
newline = ''
pos = 0
***************
*** 274,278 ****
def mimify_part(ifile, ofile, is_mime):
! '''Convert an 8bit part of a MIME mail message to quoted-printable.'''
has_cte = is_qp = is_base64 = 0
multipart = None
--- 273,277 ----
def mimify_part(ifile, ofile, is_mime):
! """Convert an 8bit part of a MIME mail message to quoted-printable."""
has_cte = is_qp = is_base64 = 0
multipart = None
***************
*** 409,413 ****
def mimify(infile, outfile):
! '''Convert 8bit parts of a MIME mail message to quoted-printable.'''
if type(infile) == type(''):
ifile = open(infile)
--- 408,412 ----
def mimify(infile, outfile):
! """Convert 8bit parts of a MIME mail message to quoted-printable."""
if type(infile) == type(''):
ifile = open(infile)
Index: multifile.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/multifile.py,v
retrieving revision 1.8
retrieving revision 1.9
diff -C2 -r1.8 -r1.9
*** multifile.py 1998/06/29 17:58:43 1.8
--- multifile.py 2000/02/04 15:10:33 1.9
***************
*** 1,28 ****
! # A class that makes each part of a multipart message "feel" like an
! # ordinary file, as long as you use fp.readline(). Allows recursive
! # use, for nested multipart messages. Probably best used together
! # with module mimetools.
! #
! # Suggested use:
! #
! # real_fp = open(...)
! # fp = MultiFile(real_fp)
! #
! # "read some lines from fp"
! # fp.push(separator)
! # while 1:
! # "read lines from fp until it returns an empty string" (A)
! # if not fp.next(): break
! # fp.pop()
! # "read remaining lines from fp until it returns an empty string"
! #
! # The latter sequence may be used recursively at (A).
! # It is also allowed to use multiple push()...pop() sequences.
! #
! # If seekable is given as 0, the class code will not do the bookeeping
! # it normally attempts in order to make seeks relative to the beginning of the
! # current file part. This may be useful when using MultiFile with a non-
! # seekable stream object.
import sys
import string
--- 1,31 ----
! """A readline()-style interface to the parts of a multipart message.
+ The MultiFile class makes each part of a multipart message "feel" like
+ an ordinary file, as long as you use fp.readline(). Allows recursive
+ use, for nested multipart messages. Probably best used together
+ with module mimetools.
+
+ Suggested use:
+
+ real_fp = open(...)
+ fp = MultiFile(real_fp)
+
+ "read some lines from fp"
+ fp.push(separator)
+ while 1:
+ "read lines from fp until it returns an empty string" (A)
+ if not fp.next(): break
+ fp.pop()
+ "read remaining lines from fp until it returns an empty string"
+
+ The latter sequence may be used recursively at (A).
+ It is also allowed to use multiple push()...pop() sequences.
+
+ If seekable is given as 0, the class code will not do the bookeeping
+ it normally attempts in order to make seeks relative to the beginning of the
+ current file part. This may be useful when using MultiFile with a non-
+ seekable stream object.
+ """
+
import sys
import string
***************
*** 31,37 ****
class MultiFile:
! #
seekable = 0
! #
def __init__(self, fp, seekable=1):
self.fp = fp
--- 34,40 ----
class MultiFile:
!
seekable = 0
!
def __init__(self, fp, seekable=1):
self.fp = fp
***************
*** 43,52 ****
self.start = self.fp.tell()
self.posstack = [] # Grows down
! #
def tell(self):
if self.level > 0:
return self.lastpos
return self.fp.tell() - self.start
! #
def seek(self, pos, whence=0):
here = self.tell()
--- 46,55 ----
self.start = self.fp.tell()
self.posstack = [] # Grows down
!
def tell(self):
if self.level > 0:
return self.lastpos
return self.fp.tell() - self.start
!
def seek(self, pos, whence=0):
here = self.tell()
***************
*** 65,69 ****
self.level = 0
self.last = 0
! #
def readline(self):
if self.level > 0:
--- 68,72 ----
self.level = 0
self.last = 0
!
def readline(self):
if self.level > 0:
***************
*** 106,110 ****
raise Error,'Missing endmarker in MultiFile.readline()'
return ''
! #
def readlines(self):
list = []
--- 109,113 ----
raise Error,'Missing endmarker in MultiFile.readline()'
return ''
!
def readlines(self):
list = []
***************
*** 114,121 ****
list.append(line)
return list
! #
def read(self): # Note: no size argument -- read until EOF only!
return string.joinfields(self.readlines(), '')
! #
def next(self):
while self.readline(): pass
--- 117,124 ----
list.append(line)
return list
!
def read(self): # Note: no size argument -- read until EOF only!
return string.joinfields(self.readlines(), '')
!
def next(self):
while self.readline(): pass
***************
*** 127,131 ****
self.start = self.fp.tell()
return 1
! #
def push(self, sep):
if self.level > 0:
--- 130,134 ----
self.start = self.fp.tell()
return 1
!
def push(self, sep):
if self.level > 0:
***************
*** 135,139 ****
self.posstack.insert(0, self.start)
self.start = self.fp.tell()
! #
def pop(self):
if self.stack == []:
--- 138,142 ----
self.posstack.insert(0, self.start)
self.start = self.fp.tell()
!
def pop(self):
if self.stack == []:
***************
*** 150,160 ****
if self.level > 0:
self.lastpos = abslastpos - self.start
! #
def is_data(self, line):
return line[:2] <> '--'
! #
def section_divider(self, str):
return "--" + str
! #
def end_marker(self, str):
return "--" + str + "--"
--- 153,163 ----
if self.level > 0:
self.lastpos = abslastpos - self.start
!
def is_data(self, line):
return line[:2] <> '--'
!
def section_divider(self, str):
return "--" + str
!
def end_marker(self, str):
return "--" + str + "--"
Index: mutex.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/mutex.py,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -r1.5 -r1.6
*** mutex.py 1996/10/08 14:06:17 1.5
--- mutex.py 2000/02/04 15:10:33 1.6
***************
*** 1,32 ****
! # Mutual exclusion -- for use with module sched
! # A mutex has two pieces of state -- a 'locked' bit and a queue.
! # When the mutex is not locked, the queue is empty.
! # Otherwise, the queue contains 0 or more (function, argument) pairs
! # representing functions (or methods) waiting to acquire the lock.
! # When the mutex is unlocked while the queue is not empty,
! # the first queue entry is removed and its function(argument) pair called,
! # implying it now has the lock.
! #
! # Of course, no multi-threading is implied -- hence the funny interface
! # for lock, where a function is called once the lock is aquired.
! #
class mutex:
- #
- # Create a new mutex -- initially unlocked
- #
def __init__(self):
self.locked = 0
self.queue = []
! #
! # Test the locked bit of the mutex
! #
def test(self):
return self.locked
! #
! # Atomic test-and-set -- grab the lock if it is not set,
! # return true if it succeeded
! #
def testandset(self):
if not self.locked:
self.locked = 1
--- 1,29 ----
! """Mutual exclusion -- for use with module sched
! A mutex has two pieces of state -- a 'locked' bit and a queue.
! When the mutex is not locked, the queue is empty.
! Otherwise, the queue contains 0 or more (function, argument) pairs
! representing functions (or methods) waiting to acquire the lock.
! When the mutex is unlocked while the queue is not empty,
! the first queue entry is removed and its function(argument) pair called,
! implying it now has the lock.
!
! Of course, no multi-threading is implied -- hence the funny interface
! for lock, where a function is called once the lock is aquired.
! """
!
class mutex:
def __init__(self):
+ """Create a new mutex -- initially unlocked."""
self.locked = 0
self.queue = []
!
def test(self):
+ """Test the locked bit of the mutex."""
return self.locked
!
def testandset(self):
+ """Atomic test-and-set -- grab the lock if it is not set,
+ return true if it succeeded."""
if not self.locked:
self.locked = 1
***************
*** 34,53 ****
else:
return 0
! #
! # Lock a mutex, call the function with supplied argument
! # when it is acquired.
! # If the mutex is already locked, place function and argument
! # in the queue.
! #
def lock(self, function, argument):
if self.testandset():
function(argument)
else:
self.queue.append((function, argument))
! #
! # Unlock a mutex. If the queue is not empty, call the next
! # function with its argument.
! #
def unlock(self):
if self.queue:
function, argument = self.queue[0]
--- 31,47 ----
else:
return 0
!
def lock(self, function, argument):
+ """Lock a mutex, call the function with supplied argument
+ when it is acquired. If the mutex is already locked, place
+ function and argument in the queue."""
if self.testandset():
function(argument)
else:
self.queue.append((function, argument))
!
def unlock(self):
+ """Unlock a mutex. If the queue is not empty, call the next
+ function with its argument."""
if self.queue:
function, argument = self.queue[0]
***************
*** 56,58 ****
else:
self.locked = 0
- #
--- 50,51 ----
Index: netrc.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/netrc.py,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -r1.3 -r1.4
*** netrc.py 1999/05/03 18:10:37 1.3
--- netrc.py 2000/02/04 15:10:33 1.4
***************
*** 1,2 ****
--- 1,4 ----
+ """An object-oriented interface to .netrc files."""
+
# Module and documentation by Eric S. Raymond, 21 Dec 1998
***************
*** 64,68 ****
def authenticators(self, host):
! "Return a (user, account, password) tuple for given host."
if self.hosts.has_key(host):
return self.hosts[host]
--- 66,70 ----
def authenticators(self, host):
! """Return a (user, account, password) tuple for given host."""
if self.hosts.has_key(host):
return self.hosts[host]
***************
*** 73,77 ****
def __repr__(self):
! "Dump the class data in the format of a .netrc file"
rep = ""
for host in self.hosts.keys():
--- 75,79 ----
def __repr__(self):
! """Dump the class data in the format of a .netrc file."""
rep = ""
for host in self.hosts.keys():
Index: nntplib.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/nntplib.py,v
retrieving revision 1.16
retrieving revision 1.17
diff -C2 -r1.16 -r1.17
*** nntplib.py 1998/12/21 18:51:23 1.16
--- nntplib.py 2000/02/04 15:10:33 1.17
***************
*** 1,30 ****
! # An NNTP client class. Based on RFC 977: Network News Transfer
! # Protocol, by Brian Kantor and Phil Lapsley.
! # Example:
! #
! # >>> from nntplib import NNTP
! # >>> s = NNTP('news')
! # >>> resp, count, first, last, name = s.group('comp.lang.python')
! # >>> print 'Group', name, 'has', count, 'articles, range', first, 'to', last
! # Group comp.lang.python has 51 articles, range 5770 to 5821
! # >>> resp, subs = s.xhdr('subject', first + '-' + last)
! # >>> resp = s.quit()
! # >>>
! #
! # Here 'resp' is the server response line.
! # Error responses are turned into exceptions.
! #
! # To post an article from a file:
! # >>> f = open(filename, 'r') # file containing article, including header
! # >>> resp = s.post(f)
! # >>>
! #
! # For descriptions of all methods, read the comments in the code below.
! # Note that all arguments and return values representing article numbers
! # are strings, not numbers, since they are rarely used for calculations.
! # (xover, xgtitle, xpath, date methods by Kevan Heydon)
--- 1,30 ----
! """An NNTP client class based on RFC 977: Network News Transfer Protocol.
+ Example:
! >>> from nntplib import NNTP
! >>> s = NNTP('news')
! >>> resp, count, first, last, name = s.group('comp.lang.python')
! >>> print 'Group', name, 'has', count, 'articles, range', first, 'to', last
! Group comp.lang.python has 51 articles, range 5770 to 5821
! >>> resp, subs = s.xhdr('subject', first + '-' + last)
! >>> resp = s.quit()
! >>>
!
! Here 'resp' is the server response line.
! Error responses are turned into exceptions.
!
! To post an article from a file:
! >>> f = open(filename, 'r') # file containing article, including header
! >>> resp = s.post(f)
! >>>
!
! For descriptions of all methods, read the comments in the code below.
! Note that all arguments and return values representing article numbers
! are strings, not numbers, since they are rarely used for calculations.
! """
! # RFC 977 by Brian Kantor and Phil Lapsley.
! # xover, xgtitle, xpath, date methods by Kevan Heydon
***************
*** 36,40 ****
# Exception raised when an error or invalid response is received
-
error_reply = 'nntplib.error_reply' # unexpected [123]xx reply
error_temp = 'nntplib.error_temp' # 4xx errors
--- 36,39 ----
***************
*** 60,68 ****
class NNTP:
- # Initialize an instance. Arguments:
- # - host: hostname to connect to
- # - port: port to connect to (default the standard NNTP port)
-
def __init__(self, host, port = NNTP_PORT, user=None, password=None):
self.host = host
self.port = port
--- 59,67 ----
class NNTP:
def __init__(self, host, port = NNTP_PORT, user=None, password=None):
+ """Initialize an instance. Arguments:
+ - host: hostname to connect to
+ - port: port to connect to (default the standard NNTP port)"""
+
self.host = host
self.port = port
***************
*** 83,118 ****
raise error_perm, resp
- # Get the welcome message from the server
- # (this is read and squirreled away by __init__()).
- # If the response code is 200, posting is allowed;
- # if it 201, posting is not allowed
-
def getwelcome(self):
if self.debugging: print '*welcome*', `self.welcome`
return self.welcome
- # Set the debugging level. Argument level means:
- # 0: no debugging output (default)
- # 1: print commands and responses but not body text etc.
- # 2: also print raw lines read and sent before stripping CR/LF
-
def set_debuglevel(self, level):
self.debugging = level
debug = set_debuglevel
- # Internal: send one line to the server, appending CRLF
def putline(self, line):
line = line + CRLF
if self.debugging > 1: print '*put*', `line`
self.sock.send(line)
- # Internal: send one command to the server (through putline())
def putcmd(self, line):
if self.debugging: print '*cmd*', `line`
self.putline(line)
- # Internal: return one line from the server, stripping CRLF.
- # Raise EOFError if the connection is closed
def getline(self):
line = self.file.readline()
if self.debugging > 1:
--- 82,117 ----
raise error_perm, resp
def getwelcome(self):
+ """Get the welcome message from the server
+ (this is read and squirreled away by __init__()).
+ If the response code is 200, posting is allowed;
+ if it 201, posting is not allowed."""
+
if self.debugging: print '*welcome*', `self.welcome`
return self.welcome
def set_debuglevel(self, level):
+ """Set the debugging level. Argument 'level' means:
+ 0: no debugging output (default)
+ 1: print commands and responses but not body text etc.
+ 2: also print raw lines read and sent before stripping CR/LF"""
+
self.debugging = level
debug = set_debuglevel
def putline(self, line):
+ """Internal: send one line to the server, appending CRLF."""
line = line + CRLF
if self.debugging > 1: print '*put*', `line`
self.sock.send(line)
def putcmd(self, line):
+ """Internal: send one command to the server (through putline())."""
if self.debugging: print '*cmd*', `line`
self.putline(line)
def getline(self):
+ """Internal: return one line from the server, stripping CRLF.
+ Raise EOFError if the connection is closed."""
line = self.file.readline()
if self.debugging > 1:
***************
*** 123,129 ****
return line
- # Internal: get a response from the server.
- # Raise various errors if the response indicates an error
def getresp(self):
resp = self.getline()
if self.debugging: print '*resp*', `resp`
--- 122,128 ----
return line
def getresp(self):
+ """Internal: get a response from the server.
+ Raise various errors if the response indicates an error."""
resp = self.getline()
if self.debugging: print '*resp*', `resp`
***************
*** 137,143 ****
return resp
- # Internal: get a response plus following text from the server.
- # Raise various errors if the response indicates an error
def getlongresp(self):
resp = self.getresp()
if resp[:3] not in LONGRESP:
--- 136,142 ----
return resp
def getlongresp(self):
+ """Internal: get a response plus following text from the server.
+ Raise various errors if the response indicates an error."""
resp = self.getresp()
if resp[:3] not in LONGRESP:
***************
*** 153,193 ****
return resp, list
- # Internal: send a command and get the response
def shortcmd(self, line):
self.putcmd(line)
return self.getresp()
- # Internal: send a command and get the response plus following text
def longcmd(self, line):
self.putcmd(line)
return self.getlongresp()
- # Process a NEWGROUPS command. Arguments:
- # - date: string 'yymmdd' indicating the date
- # - time: string 'hhmmss' indicating the time
- # Return:
- # - resp: server response if succesful
- # - list: list of newsgroup names
-
def newgroups(self, date, time):
! return self.longcmd('NEWGROUPS ' + date + ' ' + time)
! # Process a NEWNEWS command. Arguments:
! # - group: group name or '*'
! # - date: string 'yymmdd' indicating the date
! # - time: string 'hhmmss' indicating the time
! # Return:
! # - resp: server response if succesful
! # - list: list of article ids
def newnews(self, group, date, time):
cmd = 'NEWNEWS ' + group + ' ' + date + ' ' + time
return self.longcmd(cmd)
- # Process a LIST command. Return:
- # - resp: server response if succesful
- # - list: list of (group, last, first, flag) (strings)
-
def list(self):
resp, list = self.longcmd('LIST')
for i in range(len(list)):
--- 152,192 ----
return resp, list
def shortcmd(self, line):
+ """Internal: send a command and get the response."""
self.putcmd(line)
return self.getresp()
def longcmd(self, line):
+ """Internal: send a command and get the response plus following text."""
self.putcmd(line)
return self.getlongresp()
def newgroups(self, date, time):
! """Process a NEWGROUPS command. Arguments:
! - date: string 'yymmdd' indicating the date
! - time: string 'hhmmss' indicating the time
! Return:
! - resp: server response if succesful
! - list: list of newsgroup names"""
! return self.longcmd('NEWGROUPS ' + date + ' ' + time)
def newnews(self, group, date, time):
+ """Process a NEWNEWS command. Arguments:
+ - group: group name or '*'
+ - date: string 'yymmdd' indicating the date
+ - time: string 'hhmmss' indicating the time
+ Return:
+ - resp: server response if succesful
+ - list: list of article ids"""
+
cmd = 'NEWNEWS ' + group + ' ' + date + ' ' + time
return self.longcmd(cmd)
def list(self):
+ """Process a LIST command. Return:
+ - resp: server response if succesful
+ - list: list of (group, last, first, flag) (strings)"""
+
resp, list = self.longcmd('LIST')
for i in range(len(list)):
***************
*** 196,209 ****
return resp, list
- # Process a GROUP command. Argument:
- # - group: the group name
- # Returns:
- # - resp: server response if succesful
- # - count: number of articles (string)
- # - first: first article number (string)
- # - last: last article number (string)
- # - name: the group name
-
def group(self, name):
resp = self.shortcmd('GROUP ' + name)
if resp[:3] <> '211':
--- 195,208 ----
return resp, list
def group(self, name):
+ """Process a GROUP command. Argument:
+ - group: the group name
+ Returns:
+ - resp: server response if succesful
+ - count: number of articles (string)
+ - first: first article number (string)
+ - last: last article number (string)
+ - name: the group name"""
+
resp = self.shortcmd('GROUP ' + name)
if resp[:3] <> '211':
***************
*** 222,234 ****
return resp, count, first, last, name
- # Process a HELP command. Returns:
- # - resp: server response if succesful
- # - list: list of strings
-
def help(self):
return self.longcmd('HELP')
- # Internal: parse the response of a STAT, NEXT or LAST command
def statparse(self, resp):
if resp[:2] <> '22':
raise error_reply, resp
--- 221,233 ----
return resp, count, first, last, name
def help(self):
+ """Process a HELP command. Returns:
+ - resp: server response if succesful
+ - list: list of strings"""
+
return self.longcmd('HELP')
def statparse(self, resp):
+ """Internal: parse the response of a STAT, NEXT or LAST command."""
if resp[:2] <> '22':
raise error_reply, resp
***************
*** 243,324 ****
return resp, nr, id
- # Internal: process a STAT, NEXT or LAST command
def statcmd(self, line):
resp = self.shortcmd(line)
return self.statparse(resp)
- # Process a STAT command. Argument:
- # - id: article number or message id
- # Returns:
- # - resp: server response if succesful
- # - nr: the article number
- # - id: the article id
-
def stat(self, id):
! return self.statcmd('STAT ' + id)
! # Process a NEXT command. No arguments. Return as for STAT
def next(self):
return self.statcmd('NEXT')
- # Process a LAST command. No arguments. Return as for STAT
-
def last(self):
return self.statcmd('LAST')
- # Internal: process a HEAD, BODY or ARTICLE command
def artcmd(self, line):
resp, list = self.longcmd(line)
resp, nr, id = self.statparse(resp)
return resp, nr, id, list
- # Process a HEAD command. Argument:
- # - id: article number or message id
- # Returns:
- # - resp: server response if succesful
- # - nr: article number
- # - id: message id
- # - list: the lines of the article's header
-
def head(self, id):
! return self.artcmd('HEAD ' + id)
! # Process a BODY command. Argument:
! # - id: article number or message id
! # Returns:
! # - resp: server response if succesful
! # - nr: article number
! # - id: message id
! # - list: the lines of the article's body
def body(self, id):
! return self.artcmd('BODY ' + id)
! # Process an ARTICLE command. Argument:
! # - id: article number or message id
! # Returns:
! # - resp: server response if succesful
! # - nr: article number
! # - id: message id
! # - list: the lines of the article
def article(self, id):
! return self.artcmd('ARTICLE ' + id)
! # Process a SLAVE command. Returns:
! # - resp: server response if succesful
def slave(self):
! return self.shortcmd('SLAVE')
! # Process an XHDR command (optional server extension). Arguments:
! # - hdr: the header type (e.g. 'subject')
! # - str: an article nr, a message id, or a range nr1-nr2
! # Returns:
! # - resp: server response if succesful
! # - list: list of (nr, value) strings
def xhdr(self, hdr, str):
pat = re.compile('^([0-9]+) ?(.*)\n?')
resp, lines = self.longcmd('XHDR ' + hdr + ' ' + str)
--- 242,321 ----
return resp, nr, id
def statcmd(self, line):
+ """Internal: process a STAT, NEXT or LAST command."""
resp = self.shortcmd(line)
return self.statparse(resp)
def stat(self, id):
! """Process a STAT command. Argument:
! - id: article number or message id
! Returns:
! - resp: server response if succesful
! - nr: the article number
! - id: the article id"""
! return self.statcmd('STAT ' + id)
def next(self):
+ """Process a NEXT command. No arguments. Return as for STAT."""
return self.statcmd('NEXT')
def last(self):
+ """Process a LAST command. No arguments. Return as for STAT."""
return self.statcmd('LAST')
def artcmd(self, line):
+ """Internal: process a HEAD, BODY or ARTICLE command."""
resp, list = self.longcmd(line)
resp, nr, id = self.statparse(resp)
return resp, nr, id, list
def head(self, id):
! """Process a HEAD command. Argument:
! - id: article number or message id
! Returns:
! - resp: server response if succesful
! - nr: article number
! - id: message id
! - list: the lines of the article's header"""
! return self.artcmd('HEAD ' + id)
def body(self, id):
! """Process a BODY command. Argument:
! - id: article number or message id
! Returns:
! - resp: server response if succesful
! - nr: article number
! - id: message id
! - list: the lines of the article's body"""
! return self.artcmd('BODY ' + id)
def article(self, id):
! """Process an ARTICLE command. Argument:
! - id: article number or message id
! Returns:
! - resp: server response if succesful
! - nr: article number
! - id: message id
! - list: the lines of the article"""
! return self.artcmd('ARTICLE ' + id)
def slave(self):
! """Process a SLAVE command. Returns:
! - resp: server response if succesful"""
! return self.shortcmd('SLAVE')
def xhdr(self, hdr, str):
+ """Process an XHDR command (optional server extension). Arguments:
+ - hdr: the header type (e.g. 'subject')
+ - str: an article nr, a message id, or a range nr1-nr2
+ Returns:
+ - resp: server response if succesful
+ - list: list of (nr, value) strings"""
+
pat = re.compile('^([0-9]+) ?(.*)\n?')
resp, lines = self.longcmd('XHDR ' + hdr + ' ' + str)
***************
*** 330,341 ****
return resp, lines
- # Process an XOVER command (optional server extension) Arguments:
- # - start: start of range
- # - end: end of range
- # Returns:
- # - resp: server response if succesful
- # - list: list of (art-nr, subject, poster, date, id, refrences, size, lines)
-
def xover(self,start,end):
resp, lines = self.longcmd('XOVER ' + start + '-' + end)
xover_lines = []
--- 327,339 ----
return resp, lines
def xover(self,start,end):
+ """Process an XOVER command (optional server extension) Arguments:
+ - start: start of range
+ - end: end of range
+ Returns:
+ - resp: server response if succesful
+ - list: list of (art-nr, subject, poster, date,
+ id, references, size, lines)"""
+
resp, lines = self.longcmd('XOVER ' + start + '-' + end)
xover_lines = []
***************
*** 355,365 ****
return resp,xover_lines
- # Process an XGTITLE command (optional server extension) Arguments:
- # - group: group name wildcard (i.e. news.*)
- # Returns:
- # - resp: server response if succesful
- # - list: list of (name,title) strings
-
def xgtitle(self, group):
line_pat = re.compile("^([^ \t]+)[ \t]+(.*)$")
resp, raw_lines = self.longcmd('XGTITLE ' + group)
--- 353,363 ----
return resp,xover_lines
def xgtitle(self, group):
+ """Process an XGTITLE command (optional server extension) Arguments:
+ - group: group name wildcard (i.e. news.*)
+ Returns:
+ - resp: server response if succesful
+ - list: list of (name,title) strings"""
+
line_pat = re.compile("^([^ \t]+)[ \t]+(.*)$")
resp, raw_lines = self.longcmd('XGTITLE ' + group)
***************
*** 371,381 ****
return resp, lines
- # Process an XPATH command (optional server extension) Arguments:
- # - id: Message id of article
- # Returns:
- # resp: server response if succesful
- # path: directory path to article
-
def xpath(self,id):
resp = self.shortcmd("XPATH " + id)
if resp[:3] <> '223':
--- 369,379 ----
return resp, lines
def xpath(self,id):
+ """Process an XPATH command (optional server extension) Arguments:
+ - id: Message id of article
+ Returns:
+ resp: server response if succesful
+ path: directory path to article"""
+
resp = self.shortcmd("XPATH " + id)
if resp[:3] <> '223':
***************
*** 388,399 ****
return resp, path
- # Process the DATE command. Arguments:
- # None
- # Returns:
- # resp: server response if succesful
- # date: Date suitable for newnews/newgroups commands etc.
- # time: Time suitable for newnews/newgroups commands etc.
-
def date (self):
resp = self.shortcmd("DATE")
if resp[:3] <> '111':
--- 386,397 ----
return resp, path
def date (self):
+ """Process the DATE command. Arguments:
+ None
+ Returns:
+ resp: server response if succesful
+ date: Date suitable for newnews/newgroups commands etc.
+ time: Time suitable for newnews/newgroups commands etc."""
+
resp = self.shortcmd("DATE")
if resp[:3] <> '111':
***************
*** 409,418 ****
- # Process a POST command. Arguments:
- # - f: file containing the article
- # Returns:
- # - resp: server response if succesful
-
def post(self, f):
resp = self.shortcmd('POST')
# Raises error_??? if posting is not allowed
--- 407,416 ----
def post(self, f):
+ """Process a POST command. Arguments:
+ - f: file containing the article
+ Returns:
+ - resp: server response if succesful"""
+
resp = self.shortcmd('POST')
# Raises error_??? if posting is not allowed
***************
*** 431,442 ****
return self.getresp()
- # Process an IHAVE command. Arguments:
- # - id: message-id of the article
- # - f: file containing the article
- # Returns:
- # - resp: server response if succesful
- # Note that if the server refuses the article an exception is raised
-
def ihave(self, id, f):
resp = self.shortcmd('IHAVE ' + id)
# Raises error_??? if the server already has it
--- 429,440 ----
return self.getresp()
def ihave(self, id, f):
+ """Process an IHAVE command. Arguments:
+ - id: message-id of the article
+ - f: file containing the article
+ Returns:
+ - resp: server response if succesful
+ Note that if the server refuses the article an exception is raised."""
+
resp = self.shortcmd('IHAVE ' + id)
# Raises error_??? if the server already has it
***************
*** 455,462 ****
return self.getresp()
- # Process a QUIT command and close the socket. Returns:
- # - resp: server response if succesful
-
def quit(self):
resp = self.shortcmd('QUIT')
self.file.close()
--- 453,460 ----
return self.getresp()
def quit(self):
+ """Process a QUIT command and close the socket. Returns:
+ - resp: server response if succesful"""
+
resp = self.shortcmd('QUIT')
self.file.close()
***************
*** 466,471 ****
- # Minimal test function
def _test():
s = NNTP('news')
resp, count, first, last, name = s.group('comp.lang.python')
--- 464,469 ----
def _test():
+ """Minimal test function."""
s = NNTP('news')
resp, count, first, last, name = s.group('comp.lang.python')
Index: nturl2path.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/nturl2path.py,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -r1.4 -r1.5
*** nturl2path.py 1999/03/18 14:21:41 1.4
--- nturl2path.py 2000/02/04 15:10:33 1.5
***************
*** 1,5 ****
! #
! # nturl2path convert a NT pathname to a file URL and
! # vice versa
def url2pathname(url):
--- 1,3 ----
! """Convert a NT pathname to a file URL and vice versa."""
def url2pathname(url):
***************
*** 35,39 ****
def pathname2url(p):
-
""" Convert a DOS path name to a file url...
C:\foo\bar\spam.foo
--- 33,36 ----
Index: os.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/os.py,v
retrieving revision 1.28
retrieving revision 1.29
diff -C2 -r1.28 -r1.29
*** os.py 1999/11/02 20:44:07 1.28
--- os.py 2000/02/04 15:10:33 1.29
***************
*** 1,20 ****
! # os.py -- either mac, dos or posix depending on what system we're on.
! # This exports:
! # - all functions from either posix or mac, e.g., os.unlink, os.stat, etc.
! # - os.path is either module posixpath or macpath
! # - os.name is either 'posix' or 'mac'
! # - os.curdir is a string representing the current directory ('.' or ':')
! # - os.pardir is a string representing the parent directory ('..' or '::')
! # - os.sep is the (or a most common) pathname separator ('/' or ':' or '\\')
! # - os.altsep is the alternatte pathname separator (None or '/')
! # - os.pathsep is the component separator used in $PATH etc
! # - os.defpath is the default search path for executables
! # Programs that import and use 'os' stand a better chance of being
! # portable between different platforms. Of course, they must then
! # only use functions that are defined by all platforms (e.g., unlink
! # and opendir), and leave all pathname manipulation to os.path
! # (e.g., split and join).
import sys
--- 1,21 ----
! """os.py -- either mac, dos or posix depending on what system we're on.
! This exports:
! - all functions from either posix or mac, e.g., os.unlink, os.stat, etc.
! - os.path is either module posixpath or macpath
! - os.name is either 'posix' or 'mac'
! - os.curdir is a string representing the current directory ('.' or ':')
! - os.pardir is a string representing the parent directory ('..' or '::')
! - os.sep is the (or a most common) pathname separator ('/' or ':' or '\\')
! - os.altsep is the alternatte pathname separator (None or '/')
! - os.pathsep is the component separator used in $PATH etc
! - os.defpath is the default search path for executables
! Programs that import and use 'os' stand a better chance of being
! portable between different platforms. Of course, they must then
! only use functions that are defined by all platforms (e.g., unlink
! and opendir), and leave all pathname manipulation to os.path
! (e.g., split and join).
! """
import sys
Index: pdb.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/pdb.py,v
retrieving revision 1.40
retrieving revision 1.41
diff -C2 -r1.40 -r1.41
*** pdb.py 1999/11/03 13:10:07 1.40
--- pdb.py 2000/02/04 15:10:33 1.41
***************
*** 1,5 ****
#! /usr/bin/env python
! # pdb.py -- finally, a Python debugger!
# (See pdb.doc for documentation.)
--- 1,5 ----
#! /usr/bin/env python
! """pdb.py -- finally, a Python debugger!"""
# (See pdb.doc for documentation.)
***************
*** 107,115 ****
def user_line(self, frame):
! # This function is called when we stop or break at this line
self.interaction(frame, None)
def user_return(self, frame, return_value):
! # This function is called when a return trap is set here
frame.f_locals['__return__'] = return_value
print '--Return--'
--- 107,115 ----
def user_line(self, frame):
! """This function is called when we stop or break at this line."""
self.interaction(frame, None)
def user_return(self, frame, return_value):
! """This function is called when a return trap is set here."""
frame.f_locals['__return__'] = return_value
print '--Return--'
***************
*** 117,122 ****
def user_exception(self, frame, (exc_type, exc_value, exc_traceback)):
! # This function is called if an exception occurs,
! # but only if we are to stop at or just below this level
frame.f_locals['__exception__'] = exc_type, exc_value
if type(exc_type) == type(''):
--- 117,122 ----
def user_exception(self, frame, (exc_type, exc_value, exc_traceback)):
! """This function is called if an exception occurs,
! but only if we are to stop at or just below this level."""
frame.f_locals['__exception__'] = exc_type, exc_value
if type(exc_type) == type(''):
***************
*** 149,153 ****
def precmd(self, line):
! # Handle alias expansion and ';;' separator
if not line:
return line
--- 149,153 ----
def precmd(self, line):
! """Handle alias expansion and ';;' separator."""
if not line:
return line
***************
*** 263,267 ****
# To be overridden in derived debuggers
def defaultFile(self):
! # Produce a reasonable default
filename = self.curframe.f_code.co_filename
if filename == '' and mainpyfile:
--- 263,267 ----
# To be overridden in derived debuggers
def defaultFile(self):
! """Produce a reasonable default."""
filename = self.curframe.f_code.co_filename
if filename == '' and mainpyfile:
***************
*** 385,389 ****
def do_ignore(self,arg):
! # arg is bp number followed by ignore count
args = string.split(arg)
bpnum = int(string.strip(args[0]))
--- 385,389 ----
def do_ignore(self,arg):
! """arg is bp number followed by ignore count."""
args = string.split(arg)
bpnum = int(string.strip(args[0]))
***************
*** 407,414 ****
def do_clear(self, arg):
! # Three possibilities, tried in this order:
! # clear -> clear all breaks, ask for confirmation
! # clear file:lineno -> clear all breaks at file:lineno
! # clear bpno bpno ... -> clear breakpoints by number
if not arg:
try:
--- 407,414 ----
def do_clear(self, arg):
! """Three possibilities, tried in this order:
! clear -> clear all breaks, ask for confirmation
! clear file:lineno -> clear all breaks at file:lineno
! clear bpno bpno ... -> clear breakpoints by number"""
if not arg:
try:
***************
*** 852,858 ****
help()
- # Helper function for break/clear parsing -- may be overridden
-
def lookupmodule(self, filename):
root, ext = os.path.splitext(filename)
if ext == '':
--- 852,857 ----
help()
def lookupmodule(self, filename):
+ """Helper function for break/clear parsing -- may be overridden."""
root, ext = os.path.splitext(filename)
if ext == '':
Index: pickle.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/pickle.py,v
retrieving revision 1.35
retrieving revision 1.36
diff -C2 -r1.35 -r1.36
*** pickle.py 1999/10/10 21:14:25 1.35
--- pickle.py 2000/02/04 15:10:33 1.36
***************
*** 1,3 ****
! """create portable serialized representations of Python objects.
See module cPickle for a (much) faster implementation.
--- 1,3 ----
! """Create portable serialized representations of Python objects.
See module cPickle for a (much) faster implementation.
***************
*** 24,28 ****
"""
! __version__ = "$Revision: 1.35 $" # Code version
from types import *
--- 24,28 ----
"""
! __version__ = "$Revision: 1.36 $" # Code version
from types import *
Index: pipes.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/pipes.py,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -r1.4 -r1.5
*** pipes.py 1999/05/03 18:12:36 1.4
--- pipes.py 2000/02/04 15:10:34 1.5
***************
*** 1,64 ****
! # Conversion pipeline templates
! # =============================
! # The problem:
! # ------------
! #
! # Suppose you have some data that you want to convert to another format
! # (e.g. from GIF image format to PPM image format). Maybe the
! # conversion involves several steps (e.g. piping it through compress or
! # uuencode). Some of the conversion steps may require that their input
! # is a disk file, others may be able to read standard input; similar for
! # their output. The input to the entire conversion may also be read
! # from a disk file or from an open file, and similar for its output.
! #
! # The module lets you construct a pipeline template by sticking one or
! # more conversion steps together. It will take care of creating and
! # removing temporary files if they are necessary to hold intermediate
! # data. You can then use the template to do conversions from many
! # different sources to many different destinations. The temporary
! # file names used are different each time the template is used.
! #
! # The templates are objects so you can create templates for many
! # different conversion steps and store them in a dictionary, for
! # instance.
!
!
! # Directions:
! # -----------
! #
! # To create a template:
! # t = Template()
! #
! # To add a conversion step to a template:
! # t.append(command, kind)
! # where kind is a string of two characters: the first is '-' if the
! # command reads its standard input or 'f' if it requires a file; the
! # second likewise for the output. The command must be valid /bin/sh
! # syntax. If input or output files are required, they are passed as
! # $IN and $OUT; otherwise, it must be possible to use the command in
! # a pipeline.
! #
! # To add a conversion step at the beginning:
! # t.prepend(command, kind)
! #
! # To convert a file to another file using a template:
! # sts = t.copy(infile, outfile)
! # If infile or outfile are the empty string, standard input is read or
! # standard output is written, respectively. The return value is the
! # exit status of the conversion pipeline.
! #
! # To open a file for reading or writing through a conversion pipeline:
! # fp = t.open(file, mode)
! # where mode is 'r' to read the file, or 'w' to write it -- just like
! # for the built-in function open() or for os.popen().
! #
! # To create a new template object initialized to a given one:
! # t2 = t.clone()
! #
! # For an example, see the function test() at the end of the file.
import sys
import re
--- 1,63 ----
! """Conversion pipeline templates.
+ The problem:
+ ------------
! Suppose you have some data that you want to convert to another format
! (e.g. from GIF image format to PPM image format). Maybe the
! conversion involves several steps (e.g. piping it through compress or
! uuencode). Some of the conversion steps may require that their input
! is a disk file, others may be able to read standard input; similar for
! their output. The input to the entire conversion may also be read
! from a disk file or from an open file, and similar for its output.
!
! The module lets you construct a pipeline template by sticking one or
! more conversion steps together. It will take care of creating and
! removing temporary files if they are necessary to hold intermediate
! data. You can then use the template to do conversions from many
! different sources to many different destinations. The temporary
! file names used are different each time the template is used.
!
! The templates are objects so you can create templates for many
! different conversion steps and store them in a dictionary, for
! instance.
!
!
! Directions:
! -----------
!
! To create a template:
! t = Template()
!
! To add a conversion step to a template:
! t.append(command, kind)
! where kind is a string of two characters: the first is '-' if the
! command reads its standard input or 'f' if it requires a file; the
! second likewise for the output. The command must be valid /bin/sh
! syntax. If input or output files are required, they are passed as
! $IN and $OUT; otherwise, it must be possible to use the command in
! a pipeline.
!
! To add a conversion step at the beginning:
! t.prepend(command, kind)
!
! To convert a file to another file using a template:
! sts = t.copy(infile, outfile)
! If infile or outfile are the empty string, standard input is read or
! standard output is written, respectively. The return value is the
! exit status of the conversion pipeline.
!
! To open a file for reading or writing through a conversion pipeline:
! fp = t.open(file, mode)
! where mode is 'r' to read the file, or 'w' to write it -- just like
! for the built-in function open() or for os.popen().
+ To create a new template object initialized to a given one:
+ t2 = t.clone()
+ For an example, see the function test() at the end of the file.
+ """
+
+
import sys
import re
***************
*** 82,105 ****
- # A pipeline template is a Template object:
-
class Template:
- # Template() returns a fresh pipeline template
def __init__(self):
self.debugging = 0
self.reset()
- # t.__repr__() implements `t`
def __repr__(self):
return ''
- # t.reset() restores a pipeline template to its initial state
def reset(self):
self.steps = []
- # t.clone() returns a new pipeline template with identical
- # initial state as the current one
def clone(self):
t = Template()
t.steps = self.steps[:]
--- 81,103 ----
class Template:
+ """Class representing a pipeline template."""
def __init__(self):
+ """Template() returns a fresh pipeline template."""
self.debugging = 0
self.reset()
def __repr__(self):
+ """t.__repr__() implements `t`."""
return ''
def reset(self):
+ """t.reset() restores a pipeline template to its initial state."""
self.steps = []
def clone(self):
+ """t.clone() returns a new pipeline template with identical
+ initial state as the current one."""
t = Template()
t.steps = self.steps[:]
***************
*** 107,116 ****
return t
- # t.debug(flag) turns debugging on or off
def debug(self, flag):
self.debugging = flag
- # t.append(cmd, kind) adds a new step at the end
def append(self, cmd, kind):
if type(cmd) <> type(''):
raise TypeError, \
--- 105,114 ----
return t
def debug(self, flag):
+ """t.debug(flag) turns debugging on or off."""
self.debugging = flag
def append(self, cmd, kind):
+ """t.append(cmd, kind) adds a new step at the end."""
if type(cmd) <> type(''):
raise TypeError, \
***************
*** 133,138 ****
self.steps.append((cmd, kind))
- # t.prepend(cmd, kind) adds a new step at the front
def prepend(self, cmd, kind):
if type(cmd) <> type(''):
raise TypeError, \
--- 131,136 ----
self.steps.append((cmd, kind))
def prepend(self, cmd, kind):
+ """t.prepend(cmd, kind) adds a new step at the front."""
if type(cmd) <> type(''):
raise TypeError, \
***************
*** 155,161 ****
self.steps.insert(0, (cmd, kind))
- # t.open(file, rw) returns a pipe or file object open for
- # reading or writing; the file is the other end of the pipeline
def open(self, file, rw):
if rw == 'r':
return self.open_r(file)
--- 153,159 ----
self.steps.insert(0, (cmd, kind))
def open(self, file, rw):
+ """t.open(file, rw) returns a pipe or file object open for
+ reading or writing; the file is the other end of the pipeline."""
if rw == 'r':
return self.open_r(file)
***************
*** 165,172 ****
'Template.open: rw must be \'r\' or \'w\', not ' + `rw`
- # t.open_r(file) and t.open_w(file) implement
- # t.open(file, 'r') and t.open(file, 'w') respectively
-
def open_r(self, file):
if self.steps == []:
return open(file, 'r')
--- 163,169 ----
'Template.open: rw must be \'r\' or \'w\', not ' + `rw`
def open_r(self, file):
+ """t.open_r(file) and t.open_w(file) implement
+ t.open(file, 'r') and t.open(file, 'w') respectively."""
if self.steps == []:
return open(file, 'r')
Index: popen2.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/popen2.py,v
retrieving revision 1.8
retrieving revision 1.9
diff -C2 -r1.8 -r1.9
*** popen2.py 1999/04/20 12:27:31 1.8
--- popen2.py 2000/02/04 15:10:34 1.9
***************
*** 1,2 ****
--- 1,10 ----
+ """Spawn a command with pipes to its stdin, stdout, and optionally stderr.
+
+ The normal os.popen(cmd, mode) call spawns a shell command and provides a
+ file interface to just the input or output of the process depending on
+ whether mode is 'r' or 'w'. This module provides the functions popen2(cmd)
+ and popen3(cmd) which return two or three pipes to the spawned command.
+ """
+
import os
import sys
***************
*** 12,16 ****
--- 20,32 ----
class Popen3:
+ """Class representing a child process. Normally instances are created
+ by the factory functions popen2() and popen3()."""
+
def __init__(self, cmd, capturestderr=0, bufsize=-1):
+ """The parameter 'cmd' is the shell command to execute in a
+ sub-process. The 'capturestderr' flag, if true, specifies that
+ the object should capture standard error output of the child process.
+ The default is false. If the 'bufsize' parameter is specified, it
+ specifies the size of the I/O buffers to/from the child process."""
if type(cmd) == type(''):
cmd = ['/bin/sh', '-c', cmd]
***************
*** 52,56 ****
--- 68,75 ----
self.sts = -1 # Child not completed yet
_active.append(self)
+
def poll(self):
+ """Return the exit status of the child process if it has finished,
+ or -1 if it hasn't finished yet."""
if self.sts < 0:
try:
***************
*** 62,66 ****
--- 81,87 ----
pass
return self.sts
+
def wait(self):
+ """Wait for and return the exit status of the child process."""
pid, sts = os.waitpid(self.pid, 0)
if pid == self.pid:
***************
*** 70,73 ****
--- 91,97 ----
def popen2(cmd, bufsize=-1):
+ """Execute the shell command 'cmd' in a sub-process. If 'bufsize' is
+ specified, it sets the buffer size for the I/O pipes. The file objects
+ (child_stdout, child_stdin) are returned."""
_cleanup()
inst = Popen3(cmd, 0, bufsize)
***************
*** 75,78 ****
--- 99,105 ----
def popen3(cmd, bufsize=-1):
+ """Execute the shell command 'cmd' in a sub-process. If 'bufsize' is
+ specified, it sets the buffer size for the I/O pipes. The file objects
+ (child_stdout, child_stdin, child_stderr) are returned."""
_cleanup()
inst = Popen3(cmd, 1, bufsize)
Index: posixfile.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/posixfile.py,v
retrieving revision 1.12
retrieving revision 1.13
diff -C2 -r1.12 -r1.13
*** posixfile.py 1999/12/06 14:51:05 1.12
--- posixfile.py 2000/02/04 15:10:34 1.13
***************
*** 1,63 ****
! #
! # Start of posixfile.py
! #
!
! #
! # Extended file operations
! #
! # f = posixfile.open(filename, [mode, [bufsize]])
! # will create a new posixfile object
! #
! # f = posixfile.fileopen(fileobject)
! # will create a posixfile object from a builtin file object
! #
! # f.file()
! # will return the original builtin file object
! #
! # f.dup()
! # will return a new file object based on a new filedescriptor
! #
! # f.dup2(fd)
! # will return a new file object based on the given filedescriptor
! #
! # f.flags(mode)
! # will turn on the associated flag (merge)
! # mode can contain the following characters:
! #
! # (character representing a flag)
! # a append only flag
! # c close on exec flag
! # n no delay flag
! # s synchronization flag
! # (modifiers)
! # ! turn flags 'off' instead of default 'on'
! # = copy flags 'as is' instead of default 'merge'
! # ? return a string in which the characters represent the flags
! # that are set
! #
! # note: - the '!' and '=' modifiers are mutually exclusive.
! # - the '?' modifier will return the status of the flags after they
! # have been changed by other characters in the mode string
! #
! # f.lock(mode [, len [, start [, whence]]])
! # will (un)lock a region
! # mode can contain the following characters:
! #
! # (character representing type of lock)
! # u unlock
! # r read lock
! # w write lock
! # (modifiers)
! # | wait until the lock can be granted
! # ? return the first lock conflicting with the requested lock
! # or 'None' if there is no conflict. The lock returned is in the
! # format (mode, len, start, whence, pid) where mode is a
! # character representing the type of lock ('r' or 'w')
! #
! # note: - the '?' modifier prevents a region from being locked; it is
! # query only
! #
class _posixfile_:
states = ['open', 'closed']
--- 1,60 ----
! """Extended file operations available in POSIX.
+ f = posixfile.open(filename, [mode, [bufsize]])
+ will create a new posixfile object
+
+ f = posixfile.fileopen(fileobject)
+ will create a posixfile object from a builtin file object
+
+ f.file()
+ will return the original builtin file object
+
+ f.dup()
+ will return a new file object based on a new filedescriptor
+
+ f.dup2(fd)
+ will return a new file object based on the given filedescriptor
+
+ f.flags(mode)
+ will turn on the associated flag (merge)
+ mode can contain the following characters:
+
+ (character representing a flag)
+ a append only flag
+ c close on exec flag
+ n no delay flag
+ s synchronization flag
+ (modifiers)
+ ! turn flags 'off' instead of default 'on'
+ = copy flags 'as is' instead of default 'merge'
+ ? return a string in which the characters represent the flags
+ that are set
+
+ note: - the '!' and '=' modifiers are mutually exclusive.
+ - the '?' modifier will return the status of the flags after they
+ have been changed by other characters in the mode string
+
+ f.lock(mode [, len [, start [, whence]]])
+ will (un)lock a region
+ mode can contain the following characters:
+
+ (character representing type of lock)
+ u unlock
+ r read lock
+ w write lock
+ (modifiers)
+ | wait until the lock can be granted
+ ? return the first lock conflicting with the requested lock
+ or 'None' if there is no conflict. The lock returned is in the
+ format (mode, len, start, whence, pid) where mode is a
+ character representing the type of lock ('r' or 'w')
+
+ note: - the '?' modifier prevents a region from being locked; it is
+ query only
+ """
+
class _posixfile_:
+ """File wrapper class that provides extra POSIX file routines."""
+
states = ['open', 'closed']
***************
*** 216,226 ****
return 'w', l_len, l_start, l_whence, l_pid
- #
- # Public routine to obtain a posixfile object
- #
def open(name, mode='r', bufsize=-1):
return _posixfile_().open(name, mode, bufsize)
def fileopen(file):
return _posixfile_().fileopen(file)
--- 213,222 ----
return 'w', l_len, l_start, l_whence, l_pid
def open(name, mode='r', bufsize=-1):
+ """Public routine to open a file as a posixfile object."""
return _posixfile_().open(name, mode, bufsize)
def fileopen(file):
+ """Public routine to get a posixfile object from a Python file object."""
return _posixfile_().fileopen(file)
Index: posixpath.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/posixpath.py,v
retrieving revision 1.26
retrieving revision 1.27
diff -C2 -r1.26 -r1.27
*** posixpath.py 1999/11/02 13:28:19 1.26
--- posixpath.py 2000/02/04 15:10:34 1.27
***************
*** 1,12 ****
! # Module 'posixpath' -- common operations on Posix pathnames.
! # Some of this can actually be useful on non-Posix systems too, e.g.
! # for manipulation of the pathname component of URLs.
! # The "os.path" name is an alias for this module on Posix systems;
! # on other systems (e.g. Mac, Windows), os.path provides the same
! # operations in a manner specific to that platform, and is an alias
! # to another module (e.g. macpath, ntpath).
! """Common pathname manipulations, Posix version.
! Instead of importing this module
! directly, import os and refer to this module as os.path.
"""
--- 1,12 ----
! """Common operations on Posix pathnames.
!
! Instead of importing this module directly, import os and refer to
! this module as os.path. The "os.path" name is an alias for this
! module on Posix systems; on other systems (e.g. Mac, Windows),
! os.path provides the same operations in a manner specific to that
! platform, and is an alias to another module (e.g. macpath, ntpath).
!
! Some of this can actually be useful on non-Posix systems too, e.g.
! for manipulation of the pathname component of URLs.
"""
***************
*** 370,375 ****
- # Return an absolute path.
def abspath(path):
if not isabs(path):
path = join(os.getcwd(), path)
--- 370,375 ----
def abspath(path):
+ """Return an absolute path."""
if not isabs(path):
path = join(os.getcwd(), path)
Index: profile.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/profile.py,v
retrieving revision 1.21
retrieving revision 1.22
diff -C2 -r1.21 -r1.22
*** profile.py 1999/05/03 18:13:29 1.21
--- profile.py 2000/02/04 15:10:34 1.22
***************
*** 8,11 ****
--- 8,12 ----
# See profile.doc for more information
+ """Class for profiling Python code."""
# Copyright 1994, by InfoSeek Corporation, all rights reserved.
***************
*** 80,121 ****
- #**************************************************************************
- # class Profile documentation:
- #**************************************************************************
- # self.cur is always a tuple. Each such tuple corresponds to a stack
- # frame that is currently active (self.cur[-2]). The following are the
- # definitions of its members. We use this external "parallel stack" to
- # avoid contaminating the program that we are profiling. (old profiler
- # used to write into the frames local dictionary!!) Derived classes
- # can change the definition of some entries, as long as they leave
- # [-2:] intact.
- #
- # [ 0] = Time that needs to be charged to the parent frame's function. It is
- # used so that a function call will not have to access the timing data
- # for the parents frame.
- # [ 1] = Total time spent in this frame's function, excluding time in
- # subfunctions
- # [ 2] = Cumulative time spent in this frame's function, including time in
- # all subfunctions to this frame.
- # [-3] = Name of the function that corresonds to this frame.
- # [-2] = Actual frame that we correspond to (used to sync exception handling)
- # [-1] = Our parent 6-tuple (corresonds to frame.f_back)
- #**************************************************************************
- # Timing data for each function is stored as a 5-tuple in the dictionary
- # self.timings[]. The index is always the name stored in self.cur[4].
- # The following are the definitions of the members:
- #
- # [0] = The number of times this function was called, not counting direct
- # or indirect recursion,
- # [1] = Number of times this function appears on the stack, minus one
- # [2] = Total time spent internal to this function
- # [3] = Cumulative time that this function was present on the stack. In
- # non-recursive functions, this is the total execution time from start
- # to finish of each invocation of a function, including time spent in
- # all subfunctions.
- # [5] = A dictionary indicating for each function name, the number of times
- # it was called by us.
- #**************************************************************************
class Profile:
def __init__(self, timer=None):
--- 81,121 ----
class Profile:
+ """Profiler class.
+
+ self.cur is always a tuple. Each such tuple corresponds to a stack
+ frame that is currently active (self.cur[-2]). The following are the
+ definitions of its members. We use this external "parallel stack" to
+ avoid contaminating the program that we are profiling. (old profiler
+ used to write into the frames local dictionary!!) Derived classes
+ can change the definition of some entries, as long as they leave
+ [-2:] intact.
+
+ [ 0] = Time that needs to be charged to the parent frame's function.
+ It is used so that a function call will not have to access the
+ timing data for the parent frame.
+ [ 1] = Total time spent in this frame's function, excluding time in
+ subfunctions
+ [ 2] = Cumulative time spent in this frame's function, including time in
+ all subfunctions to this frame.
+ [-3] = Name of the function that corresonds to this frame.
+ [-2] = Actual frame that we correspond to (used to sync exception handling)
+ [-1] = Our parent 6-tuple (corresonds to frame.f_back)
+
+ Timing data for each function is stored as a 5-tuple in the dictionary
+ self.timings[]. The index is always the name stored in self.cur[4].
+ The following are the definitions of the members:
+
+ [0] = The number of times this function was called, not counting direct
+ or indirect recursion,
+ [1] = Number of times this function appears on the stack, minus one
+ [2] = Total time spent internal to this function
+ [3] = Cumulative time that this function was present on the stack. In
+ non-recursive functions, this is the total execution time from start
+ to finish of each invocation of a function, including time spent in
+ all subfunctions.
+ [5] = A dictionary indicating for each function name, the number of times
+ it was called by us.
+ """
def __init__(self, timer=None):
***************
*** 450,466 ****
- #****************************************************************************
- # OldProfile class documentation
- #****************************************************************************
- #
- # The following derived profiler simulates the old style profile, providing
- # errant results on recursive functions. The reason for the usefulnes of this
- # profiler is that it runs faster (i.e., less overhead). It still creates
- # all the caller stats, and is quite useful when there is *no* recursion
- # in the user's code.
- #
- # This code also shows how easy it is to create a modified profiler.
- #****************************************************************************
class OldProfile(Profile):
def trace_dispatch_exception(self, frame, t):
rt, rtt, rct, rfn, rframe, rcur = self.cur
--- 450,463 ----
class OldProfile(Profile):
+ """A derived profiler that simulates the old style profile, providing
+ errant results on recursive functions. The reason for the usefulness of
+ this profiler is that it runs faster (i.e., less overhead). It still
+ creates all the caller stats, and is quite useful when there is *no*
+ recursion in the user's code.
+
+ This code also shows how easy it is to create a modified profiler.
+ """
+
def trace_dispatch_exception(self, frame, t):
rt, rtt, rct, rfn, rframe, rcur = self.cur
***************
*** 510,523 ****
- #****************************************************************************
- # HotProfile class documentation
- #****************************************************************************
- #
- # This profiler is the fastest derived profile example. It does not
- # calculate caller-callee relationships, and does not calculate cumulative
- # time under a function. It only calculates time spent in a function, so
- # it runs very quickly (re: very low overhead)
- #****************************************************************************
class HotProfile(Profile):
def trace_dispatch_exception(self, frame, t):
rt, rtt, rfn, rframe, rcur = self.cur
--- 507,517 ----
class HotProfile(Profile):
+ """The fastest derived profile example. It does not calculate
+ caller-callee relationships, and does not calculate cumulative
+ time under a function. It only calculates time spent in a
+ function, so it runs very quickly due to its very low overhead.
+ """
+
def trace_dispatch_exception(self, frame, t):
rt, rtt, rfn, rframe, rcur = self.cur
Index: pstats.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/pstats.py,v
retrieving revision 1.6
retrieving revision 1.7
diff -C2 -r1.6 -r1.7
*** pstats.py 1999/04/13 04:24:22 1.6
--- pstats.py 2000/02/04 15:10:34 1.7
***************
*** 1,3 ****
! #
# Class for printing reports on profiled python code. rev 1.0 4/1/94
#
--- 1,4 ----
! """Class for printing reports on profiled python code."""
!
# Class for printing reports on profiled python code. rev 1.0 4/1/94
#
***************
*** 38,76 ****
import re
- #**************************************************************************
- # Class Stats documentation
- #**************************************************************************
- # This class is used for creating reports from data generated by the
- # Profile class. It is a "friend" of that class, and imports data either
- # by direct access to members of Profile class, or by reading in a dictionary
- # that was emitted (via marshal) from the Profile class.
- #
- # The big change from the previous Profiler (in terms of raw functionality)
- # is that an "add()" method has been provided to combine Stats from
- # several distinct profile runs. Both the constructor and the add()
- # method now take arbitrarilly many file names as arguments.
- #
- # All the print methods now take an argument that indicats how many lines
- # to print. If the arg is a floating point number between 0 and 1.0, then
- # it is taken as a decimal percentage of the availabel lines to be printed
- # (e.g., .1 means print 10% of all available lines). If it is an integer,
- # it is taken to mean the number of lines of data that you wish to have
- # printed.
- #
- # The sort_stats() method now processes some additionaly options (i.e., in
- # addition to the old -1, 0, 1, or 2). It takes an arbitrary number of quoted
- # strings to select the sort order. For example sort_stats('time', 'name')
- # sorts on the major key of "internal function time", and on the minor
- # key of 'the name of the function'. Look at the two tables in sort_stats()
- # and get_sort_arg_defs(self) for more examples.
- #
- # All methods now return "self", so you can string together commands like:
- # Stats('foo', 'goo').strip_dirs().sort_stats('calls').\
- # print_stats(5).print_callers(5)
- #
- #**************************************************************************
import fpformat
class Stats:
def __init__(self, *args):
if not len(args):
--- 39,74 ----
import re
import fpformat
class Stats:
+ """This class is used for creating reports from data generated by the
+ Profile class. It is a "friend" of that class, and imports data either
+ by direct access to members of Profile class, or by reading in a dictionary
+ that was emitted (via marshal) from the Profile class.
+
+ The big change from the previous Profiler (in terms of raw functionality)
+ is that an "add()" method has been provided to combine Stats from
+ several distinct profile runs. Both the constructor and the add()
+ method now take arbitrarilly many file names as arguments.
+
+ All the print methods now take an argument that indicats how many lines
+ to print. If the arg is a floating point number between 0 and 1.0, then
+ it is taken as a decimal percentage of the availabel lines to be printed
+ (e.g., .1 means print 10% of all available lines). If it is an integer,
+ it is taken to mean the number of lines of data that you wish to have
+ printed.
+
+ The sort_stats() method now processes some additionaly options (i.e., in
+ addition to the old -1, 0, 1, or 2). It takes an arbitrary number of quoted
+ strings to select the sort order. For example sort_stats('time', 'name')
+ sorts on the major key of "internal function time", and on the minor
+ key of 'the name of the function'. Look at the two tables in sort_stats()
+ and get_sort_arg_defs(self) for more examples.
+
+ All methods now return "self", so you can string together commands like:
+ Stats('foo', 'goo').strip_dirs().sort_stats('calls').\
+ print_stats(5).print_callers(5)
+ """
+
def __init__(self, *args):
if not len(args):
***************
*** 183,188 ****
}
- # Expand all abbreviations that are unique
def get_sort_arg_defs(self):
if not self.sort_arg_dict:
self.sort_arg_dict = dict = {}
--- 181,186 ----
}
def get_sort_arg_defs(self):
+ """Expand all abbreviations that are unique."""
if not self.sort_arg_dict:
self.sort_arg_dict = dict = {}
***************
*** 290,296 ****
return
! #******************************************************************
# The following functions support actual printing of reports
! #******************************************************************
# Optional "amount" is either a line count, or a percentage of lines.
--- 288,294 ----
return
! #******************************************************************
# The following functions support actual printing of reports
! #******************************************************************
# Optional "amount" is either a line count, or a percentage of lines.
***************
*** 448,462 ****
- #**************************************************************************
- # class TupleComp Documentation
- #**************************************************************************
- # This class provides a generic function for comparing any two tuples.
- # Each instance records a list of tuple-indicies (from most significant
- # to least significant), and sort direction (ascending or decending) for
- # each tuple-index. The compare functions can then be used as the function
- # argument to the system sort() function when a list of tuples need to be
- # sorted in the instances order.
- #**************************************************************************
class TupleComp:
def __init__(self, comp_select_list):
self.comp_select_list = comp_select_list
--- 446,457 ----
class TupleComp:
+ """This class provides a generic function for comparing any two tuples.
+ Each instance records a list of tuple-indicies (from most significant
+ to least significant), and sort direction (ascending or decending) for
+ each tuple-index. The compare functions can then be used as the function
+ argument to the system sort() function when a list of tuples need to be
+ sorted in the instances order."""
+
def __init__(self, comp_select_list):
self.comp_select_list = comp_select_list
***************
*** 496,501 ****
#**************************************************************************
! # Add together all the stats for two profile entries
! def add_func_stats(target, source):
cc, nc, tt, ct, callers = source
t_cc, t_nc, t_tt, t_ct, t_callers = target
--- 491,496 ----
#**************************************************************************
! def add_func_stats(target, source):
! """Add together all the stats for two profile entries."""
cc, nc, tt, ct, callers = source
t_cc, t_nc, t_tt, t_ct, t_callers = target
***************
*** 504,509 ****
- # Combine two caller lists in a single list.
def add_callers(target, source):
new_callers = {}
for func in target.keys():
--- 499,504 ----
def add_callers(target, source):
+ """Combine two caller lists in a single list."""
new_callers = {}
for func in target.keys():
***************
*** 516,521 ****
return new_callers
- # Sum the caller statistics to get total number of calls recieved
def count_calls(callers):
nc = 0
for func in callers.keys():
--- 511,516 ----
return new_callers
def count_calls(callers):
+ """Sum the caller statistics to get total number of calls received."""
nc = 0
for func in callers.keys():
***************
*** 529,532 ****
def f8(x):
return string.rjust(fpformat.fix(x, 3), 8)
-
--- 524,526 ----
Index: pty.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/pty.py,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -r1.2 -r1.3
*** pty.py 1999/05/03 18:13:51 1.2
--- pty.py 2000/02/04 15:10:34 1.3
***************
*** 1,3 ****
! # pty.py -- Pseudo terminal utilities.
# Bugs: No signal handling. Doesn't set slave termios and window size.
--- 1,3 ----
! """Pseudo terminal utilities."""
# Bugs: No signal handling. Doesn't set slave termios and window size.
***************
*** 17,22 ****
CHILD = 0
- # Open pty master. Returns (master_fd, tty_name). SGI and Linux/BSD version.
def master_open():
try:
import sgi
--- 17,23 ----
CHILD = 0
def master_open():
+ """Open pty master and return (master_fd, tty_name).
+ SGI and Linux/BSD version."""
try:
import sgi
***************
*** 39,50 ****
raise os.error, 'out of pty devices'
- # Open the pty slave. Acquire the controlling terminal.
- # Returns file descriptor. Linux version. (Should be universal? --Guido)
def slave_open(tty_name):
return os.open(tty_name, FCNTL.O_RDWR)
- # Fork and make the child a session leader with a controlling terminal.
- # Returns (pid, master_fd)
def fork():
master_fd, tty_name = master_open()
pid = os.fork()
--- 40,52 ----
raise os.error, 'out of pty devices'
def slave_open(tty_name):
+ """Open the pty slave and acquire the controlling terminal.
+ Return the file descriptor. Linux version."""
+ # (Should be universal? --Guido)
return os.open(tty_name, FCNTL.O_RDWR)
def fork():
+ """Fork and make the child a session leader with a controlling terminal.
+ Return (pid, master_fd)."""
master_fd, tty_name = master_open()
pid = os.fork()
***************
*** 67,85 ****
return pid, master_fd
- # Write all the data to a descriptor.
def writen(fd, data):
while data != '':
n = os.write(fd, data)
data = data[n:]
- # Default read function.
def read(fd):
return os.read(fd, 1024)
- # Parent copy loop.
- # Copies
- # pty master -> standard output (master_read)
- # standard input -> pty master (stdin_read)
def copy(master_fd, master_read=read, stdin_read=read):
while 1:
rfds, wfds, xfds = select(
--- 69,87 ----
return pid, master_fd
def writen(fd, data):
+ """Write all the data to a descriptor."""
while data != '':
n = os.write(fd, data)
data = data[n:]
def read(fd):
+ """Default read function."""
return os.read(fd, 1024)
def copy(master_fd, master_read=read, stdin_read=read):
+ """Parent copy loop.
+ Copies
+ pty master -> standard output (master_read)
+ standard input -> pty master (stdin_read)"""
while 1:
rfds, wfds, xfds = select(
***************
*** 92,97 ****
writen(master_fd, data)
- # Create a spawned process.
def spawn(argv, master_read=read, stdin_read=read):
if type(argv) == type(''):
argv = (argv,)
--- 94,99 ----
writen(master_fd, data)
def spawn(argv, master_read=read, stdin_read=read):
+ """Create a spawned process."""
if type(argv) == type(''):
argv = (argv,)
Index: py_compile.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/py_compile.py,v
retrieving revision 1.14
retrieving revision 1.15
diff -C2 -r1.14 -r1.15
*** py_compile.py 1998/10/07 14:06:03 1.14
--- py_compile.py 2000/02/04 15:10:34 1.15
***************
*** 8,12 ****
def wr_long(f, x):
! "Internal; write a 32-bit int to a file in little-endian order."
f.write(chr( x & 0xff))
f.write(chr((x >> 8) & 0xff))
--- 8,12 ----
def wr_long(f, x):
! """Internal; write a 32-bit int to a file in little-endian order."""
f.write(chr( x & 0xff))
f.write(chr((x >> 8) & 0xff))
From guido@cnri.reston.va.us Fri Feb 4 15:28:48 2000
From: guido@cnri.reston.va.us (Guido van Rossum)
Date: Fri, 4 Feb 2000 10:28:48 -0500 (EST)
Subject: [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
Message-ID: <200002041528.KAA09987@eric.cnri.reston.va.us>
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
--- 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
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_ 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_ 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('') --> '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:
- # :///;?#
- # 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:
+ :///;?#
+ 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(' 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(' 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(' 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('
Update of /projects/cvsroot/python/dist/src/Lib
In directory eric:/projects/python/develop/guido/src/Lib
Modified Files:
asynchat.py asyncore.py binhex.py copy.py dircache.py
dospath.py formatter.py ftplib.py getopt.py gzip.py locale.py
macurl2path.py mimify.py os.py pdb.py pyclbr.py sched.py
smtplib.py statcache.py xmllib.py
Log Message:
Actually, the previous batch's comment should have been different;
*this* set of patches is Ka-Ping's final sweep:
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: asynchat.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/asynchat.py,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -r1.4 -r1.5
*** asynchat.py 1999/09/14 20:17:50 1.4
--- asynchat.py 2000/02/04 15:39:29 1.5
***************
*** 26,50 ****
# ======================================================================
! import socket
! import asyncore
! import string
! # This class adds support for 'chat' style protocols - where one side
! # sends a 'command', and the other sends a response (examples would be
! # the common internet protocols - smtp, nntp, ftp, etc..).
! # The handle_read() method looks at the input stream for the current
! # 'terminator' (usually '\r\n' for single-line responses, '\r\n.\r\n'
! # for multi-line output), calling self.found_terminator() on its
! # receipt.
! # for example:
! # Say you build an async nntp client using this class. At the start
! # of the connection, you'll have self.terminator set to '\r\n', in
! # order to process the single-line greeting. Just before issuing a
! # 'LIST' command you'll set it to '\r\n.\r\n'. The output of the LIST
! # command will be accumulated (using your own 'collect_incoming_data'
! # method) up to the terminator, and then control will be returned to
! # you - by calling your self.found_terminator() method
class async_chat (asyncore.dispatcher):
--- 26,53 ----
# ======================================================================
! """A class supporting chat-style (command/response) protocols.
!
! This class adds support for 'chat' style protocols - where one side
! sends a 'command', and the other sends a response (examples would be
! the common internet protocols - smtp, nntp, ftp, etc..).
! The handle_read() method looks at the input stream for the current
! 'terminator' (usually '\r\n' for single-line responses, '\r\n.\r\n'
! for multi-line output), calling self.found_terminator() on its
! receipt.
! for example:
! Say you build an async nntp client using this class. At the start
! of the connection, you'll have self.terminator set to '\r\n', in
! order to process the single-line greeting. Just before issuing a
! 'LIST' command you'll set it to '\r\n.\r\n'. The output of the LIST
! command will be accumulated (using your own 'collect_incoming_data'
! method) up to the terminator, and then control will be returned to
! you - by calling your self.found_terminator() method.
! """
! import socket
! import asyncore
! import string
class async_chat (asyncore.dispatcher):
Index: asyncore.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/asyncore.py,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -r1.3 -r1.4
*** asyncore.py 1999/09/14 20:15:19 1.3
--- asyncore.py 2000/02/04 15:39:29 1.4
***************
*** 26,29 ****
--- 26,50 ----
# ======================================================================
+ """Basic infrastructure for asynchronous socket service clients and servers.
+
+ There are only two ways to have a program on a single processor do "more
+ than one thing at a time". Multi-threaded programming is the simplest and
+ most popular way to do it, but there is another very different technique,
+ that lets you have nearly all the advantages of multi-threading, without
+ actually using multiple threads. it's really only practical if your program
+ is largely I/O bound. If your program is CPU bound, then pre-emptive
+ scheduled threads are probably what you really need. Network servers are
+ rarely CPU-bound, however.
+
+ If your operating system supports the select() system call in its I/O
+ library (and nearly all do), then you can use it to juggle multiple
+ communication channels at once; doing other work while your I/O is taking
+ place in the "background." Although this strategy can seem strange and
+ complex, especially at first, it is in many ways easier to understand and
+ control than multi-threaded programming. The module documented here solves
+ many of the difficult problems for you, making the task of building
+ sophisticated high-performance network servers and clients a snap.
+ """
+
import select
import socket
Index: binhex.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/binhex.py,v
retrieving revision 1.11
retrieving revision 1.12
diff -C2 -r1.11 -r1.12
*** binhex.py 2000/02/02 15:10:14 1.11
--- binhex.py 2000/02/04 15:39:29 1.12
***************
*** 1,3 ****
! """binhex - Macintosh binhex compression/decompression
easy interface:
--- 1,3 ----
! """Macintosh binhex compression/decompression.
easy interface:
Index: copy.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/copy.py,v
retrieving revision 1.13
retrieving revision 1.14
diff -C2 -r1.13 -r1.14
*** copy.py 1999/01/25 21:37:02 1.13
--- copy.py 2000/02/04 15:39:29 1.14
***************
*** 1,5 ****
! """\
! Generic (shallow and deep) copying operations
! =============================================
Interface summary:
--- 1,3 ----
! """Generic (shallow and deep) copying operations.
Interface summary:
Index: dircache.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/dircache.py,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -r1.5 -r1.6
*** dircache.py 2000/02/02 15:10:14 1.5
--- dircache.py 2000/02/04 15:39:29 1.6
***************
*** 1,5 ****
! """Return a sorted list of the files in a directory, using a cache
! to avoid reading the directory more often than necessary.
! Also contains a subroutine to append slashes to directories."""
import os
--- 1,7 ----
! """Read and cache directory listings.
!
! The listdir() routine returns a sorted list of the files in a directory,
! using a cache to avoid reading the directory more often than necessary.
! The annotate() routine appends slashes to directories."""
import os
Index: dospath.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/dospath.py,v
retrieving revision 1.11
retrieving revision 1.12
diff -C2 -r1.11 -r1.12
*** dospath.py 2000/02/04 15:10:32 1.11
--- dospath.py 2000/02/04 15:39:29 1.12
***************
*** 1,3 ****
! """Module 'dospath' -- common operations on DOS pathnames"""
import os
--- 1,3 ----
! """Common operations on DOS pathnames."""
import os
Index: formatter.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/formatter.py,v
retrieving revision 1.14
retrieving revision 1.15
diff -C2 -r1.14 -r1.15
*** formatter.py 1999/01/12 18:13:27 1.14
--- formatter.py 2000/02/04 15:39:29 1.15
***************
*** 1,2 ****
--- 1,22 ----
+ """Generic output formatting.
+
+ Formatter objects transform an abstract flow of formatting events into
+ specific output events on writer objects. Formatters manage several stack
+ structures to allow various properties of a writer object to be changed and
+ restored; writers need not be able to handle relative changes nor any sort
+ of ``change back'' operation. Specific writer properties which may be
+ controlled via formatter objects are horizontal alignment, font, and left
+ margin indentations. A mechanism is provided which supports providing
+ arbitrary, non-exclusive style settings to a writer as well. Additional
+ interfaces facilitate formatting events which are not reversible, such as
+ paragraph separation.
+
+ Writer objects encapsulate device interfaces. Abstract devices, such as
+ file formats, are supported as well as physical devices. The provided
+ implementations all work with abstract devices. The interface makes
+ available mechanisms for setting the properties which formatter objects
+ manage and inserting data into the output.
+ """
+
import string
import sys
Index: ftplib.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/ftplib.py,v
retrieving revision 1.39
retrieving revision 1.40
diff -C2 -r1.39 -r1.40
*** ftplib.py 1999/08/18 21:51:10 1.39
--- ftplib.py 2000/02/04 15:39:29 1.40
***************
*** 1,3 ****
! '''An FTP client class, and some helper functions.
Based on RFC 959: File Transfer Protocol
(FTP), by J. Postel and J. Reynolds
--- 1,4 ----
! """An FTP client class and some helper functions.
!
Based on RFC 959: File Transfer Protocol
(FTP), by J. Postel and J. Reynolds
***************
*** 32,36 ****
A nice test that reveals some of the network dialogue would be:
python ftplib.py -d localhost -l -p -l
! '''
--- 33,37 ----
A nice test that reveals some of the network dialogue would be:
python ftplib.py -d localhost -l -p -l
! """
Index: getopt.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/getopt.py,v
retrieving revision 1.8
retrieving revision 1.9
diff -C2 -r1.8 -r1.9
*** getopt.py 1999/12/21 22:38:40 1.8
--- getopt.py 2000/02/04 15:39:29 1.9
***************
*** 1,3 ****
! """Module getopt -- Parser for command line options.
This module helps scripts to parse the command line arguments in
--- 1,3 ----
! """Parser for command line options.
This module helps scripts to parse the command line arguments in
Index: gzip.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/gzip.py,v
retrieving revision 1.16
retrieving revision 1.17
diff -C2 -r1.16 -r1.17
*** gzip.py 2000/02/04 15:10:32 1.16
--- gzip.py 2000/02/04 15:39:29 1.17
***************
*** 1,3 ****
! """This module implements a function that reads and writes a gzipped file.
The user of the file doesn't have to worry about the compression,
but random access is not allowed."""
--- 1,4 ----
! """Functions that read and write gzipped files.
!
The user of the file doesn't have to worry about the compression,
but random access is not allowed."""
Index: locale.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/locale.py,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -r1.3 -r1.4
*** locale.py 1998/03/26 21:12:22 1.3
--- locale.py 2000/02/04 15:39:29 1.4
***************
*** 1,3 ****
! "Support for number formatting using the current locale settings"
# Author: Martin von Loewis
--- 1,4 ----
! """Support for number formatting using the current locale settings."""
!
# Author: Martin von Loewis
Index: macurl2path.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/macurl2path.py,v
retrieving revision 1.6
retrieving revision 1.7
diff -C2 -r1.6 -r1.7
*** macurl2path.py 1999/06/01 14:36:56 1.6
--- macurl2path.py 2000/02/04 15:39:29 1.7
***************
*** 1,4 ****
! """Mac specific module for conversion between pathnames and URLs.
! Do not import directly, use urllib instead."""
import string
--- 1,5 ----
! """Macintosh-specific module for conversion between pathnames and URLs.
!
! Do not import directly; use urllib instead."""
import string
Index: mimify.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/mimify.py,v
retrieving revision 1.14
retrieving revision 1.15
diff -C2 -r1.14 -r1.15
*** mimify.py 2000/02/04 15:10:33 1.14
--- mimify.py 2000/02/04 15:39:29 1.15
***************
*** 1,5 ****
#! /usr/bin/env python
! '''Mimification and unmimification of mail messages.
Decode quoted-printable parts of a mail message or encode using
--- 1,5 ----
#! /usr/bin/env python
! """Mimification and unmimification of mail messages.
Decode quoted-printable parts of a mail message or encode using
***************
*** 20,24 ****
to encode and decode respectively. Infile defaults to standard
input and outfile to standard output.
! '''
# Configure
--- 20,24 ----
to encode and decode respectively. Infile defaults to standard
input and outfile to standard output.
! """
# Configure
Index: os.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/os.py,v
retrieving revision 1.29
retrieving revision 1.30
diff -C2 -r1.29 -r1.30
*** os.py 2000/02/04 15:10:33 1.29
--- os.py 2000/02/04 15:39:30 1.30
***************
*** 1,13 ****
! """os.py -- either mac, dos or posix depending on what system we're on.
This exports:
! - all functions from either posix or mac, e.g., os.unlink, os.stat, etc.
! - os.path is either module posixpath or macpath
! - os.name is either 'posix' or 'mac'
- os.curdir is a string representing the current directory ('.' or ':')
- os.pardir is a string representing the parent directory ('..' or '::')
- os.sep is the (or a most common) pathname separator ('/' or ':' or '\\')
! - os.altsep is the alternatte pathname separator (None or '/')
- os.pathsep is the component separator used in $PATH etc
- os.defpath is the default search path for executables
--- 1,14 ----
! """OS routines for Mac, DOS, NT, or Posix depending on what system we're on.
This exports:
! - all functions from posix, nt, dos, os2, mac, or ce, e.g. unlink, stat, etc.
! - os.path is one of the modules posixpath, ntpath, macpath, or dospath
! - os.name is 'posix', 'nt', 'dos', 'os2', 'mac', or 'ce'
- os.curdir is a string representing the current directory ('.' or ':')
- os.pardir is a string representing the parent directory ('..' or '::')
- os.sep is the (or a most common) pathname separator ('/' or ':' or '\\')
! - os.altsep is the alternate pathname separator (None or '/')
- os.pathsep is the component separator used in $PATH etc
+ - os.linesep is the line separator in text files ('\r' or '\n' or '\r\n')
- os.defpath is the default search path for executables
Index: pdb.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/pdb.py,v
retrieving revision 1.41
retrieving revision 1.42
diff -C2 -r1.41 -r1.42
*** pdb.py 2000/02/04 15:10:33 1.41
--- pdb.py 2000/02/04 15:39:30 1.42
***************
*** 1,5 ****
#! /usr/bin/env python
! """pdb.py -- finally, a Python debugger!"""
# (See pdb.doc for documentation.)
--- 1,5 ----
#! /usr/bin/env python
! """A Python debugger."""
# (See pdb.doc for documentation.)
Index: pyclbr.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/pyclbr.py,v
retrieving revision 1.14
retrieving revision 1.15
diff -C2 -r1.14 -r1.15
*** pyclbr.py 1999/06/16 12:28:12 1.14
--- pyclbr.py 2000/02/04 15:39:30 1.15
***************
*** 1,3 ****
! '''Parse a Python file and retrieve classes and methods.
Parse enough of a Python file to recognize class and method
--- 1,3 ----
! """Parse a Python file and retrieve classes and methods.
Parse enough of a Python file to recognize class and method
***************
*** 52,56 ****
hairy logic that the import locator already does. (This logic
exists coded in Python in the freeze package.)
! ''' # ' <-- bow to font lock
import os
--- 52,56 ----
hairy logic that the import locator already does. (This logic
exists coded in Python in the freeze package.)
! """
import os
Index: sched.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/sched.py,v
retrieving revision 1.10
retrieving revision 1.11
diff -C2 -r1.10 -r1.11
*** sched.py 1999/06/25 18:53:23 1.10
--- sched.py 2000/02/04 15:39:30 1.11
***************
*** 1,3 ****
! """Module sched -- a generally useful event scheduler class
Each instance of this class manages its own queue.
--- 1,3 ----
! """A generally useful event scheduler class.
Each instance of this class manages its own queue.
Index: smtplib.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/smtplib.py,v
retrieving revision 1.20
retrieving revision 1.21
diff -C2 -r1.20 -r1.21
*** smtplib.py 1999/11/28 17:11:06 1.20
--- smtplib.py 2000/02/04 15:39:30 1.21
***************
*** 1,5 ****
#! /usr/bin/env python
! '''SMTP/ESMTP client class.
Author: The Dragon De Monsyne
--- 1,5 ----
#! /usr/bin/env python
! """SMTP/ESMTP client class.
Author: The Dragon De Monsyne
***************
*** 38,42 ****
(250, "Somebody OverHere ")
>>> s.quit()
! '''
import socket
--- 38,42 ----
(250, "Somebody OverHere ")
>>> s.quit()
! """
import socket
Index: statcache.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/statcache.py,v
retrieving revision 1.6
retrieving revision 1.7
diff -C2 -r1.6 -r1.7
*** statcache.py 2000/02/04 15:28:41 1.6
--- statcache.py 2000/02/04 15:39:30 1.7
***************
*** 1,3 ****
! """Maintain a cache of file stats.
There are functions to reset the cache or to selectively remove items.
"""
--- 1,4 ----
! """Maintain a cache of stat() information on files.
!
There are functions to reset the cache or to selectively remove items.
"""
Index: xmllib.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/xmllib.py,v
retrieving revision 1.16
retrieving revision 1.17
diff -C2 -r1.16 -r1.17
*** xmllib.py 1999/08/26 15:52:33 1.16
--- xmllib.py 2000/02/04 15:39:30 1.17
***************
*** 1,3 ****
! # A parser for XML, using the derived class as static DTD.
# Author: Sjoerd Mullender.
--- 1,4 ----
! """A parser for XML, using the derived class as static DTD."""
!
# Author: Sjoerd Mullender.
From fdrake@weyr.cnri.reston.va.us Fri Feb 4 17:40:05 2000
From: fdrake@weyr.cnri.reston.va.us (Fred L. Drake)
Date: Fri, 4 Feb 2000 12:40:05 -0500 (EST)
Subject: [Python-checkins] CVS: python/dist/src/Doc/html index.html.in,1.4,1.4.4.1
Message-ID: <200002041740.MAA09963@weyr.cnri.reston.va.us>
Update of /projects/cvsroot/python/dist/src/Doc/html
In directory weyr:/home/fdrake/projects/python/Doc-152p1/html
Modified Files:
Tag: release152p1-patches
index.html.in
Log Message:
Make sure the version number in the is updated; problem
reported by Peter Funk .
Index: index.html.in
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Doc/html/index.html.in,v
retrieving revision 1.4
retrieving revision 1.4.4.1
diff -C2 -r1.4 -r1.4.4.1
*** index.html.in 1999/05/27 21:56:11 1.4
--- index.html.in 2000/02/04 17:40:02 1.4.4.1
***************
*** 1,5 ****
! Python 1.5.2 Documentation