[Python-checkins] r45654 - in python/trunk: Doc/lib/liboptparse.tex Lib/optparse.py Lib/test/test_optparse.py Misc/NEWS

greg.ward python-checkins at python.org
Sun Apr 23 05:48:00 CEST 2006


Author: greg.ward
Date: Sun Apr 23 05:47:58 2006
New Revision: 45654

Modified:
   python/trunk/Doc/lib/liboptparse.tex
   python/trunk/Lib/optparse.py
   python/trunk/Lib/test/test_optparse.py
   python/trunk/Misc/NEWS
Log:
Update optparse to Optik 1.5.1.


Modified: python/trunk/Doc/lib/liboptparse.tex
==============================================================================
--- python/trunk/Doc/lib/liboptparse.tex	(original)
+++ python/trunk/Doc/lib/liboptparse.tex	Sun Apr 23 05:47:58 2006
@@ -35,9 +35,9 @@
 \end{verbatim}
 
 As it parses the command line, \code{optparse} sets attributes of the
-\var{options} object returned by \method{parse{\_}args()} based on user-supplied
+\code{options} object returned by \method{parse{\_}args()} based on user-supplied
 command-line values.  When \method{parse{\_}args()} returns from parsing this
-command line, \var{options.filename} will be \code{"outfile"} and
+command line, \code{options.filename} will be \code{"outfile"} and
 \code{options.verbose} will be \code{False}.  \code{optparse} supports both long
 and short options, allows short options to be merged together, and
 allows options to be associated with their arguments in a variety of
@@ -100,8 +100,8 @@
 single letter, e.g. \code{"-x"} or \code{"-F"}.  Also, traditional \UNIX{}
 syntax allows multiple options to be merged into a single argument,
 e.g.  \code{"-x -F"} is equivalent to \code{"-xF"}.  The GNU project
-introduced \code{"{--}"} followed by a series of hyphen-separated words,
-e.g. \code{"{--}file"} or \code{"{--}dry-run"}.  These are the only two option
+introduced \code{"-{}-"} followed by a series of hyphen-separated words,
+e.g. \code{"-{}-file"} or \code{"-{}-dry-run"}.  These are the only two option
 syntaxes provided by \module{optparse}.
 
 Some other option syntaxes that the world has seen include:
@@ -170,7 +170,7 @@
 prog -v --report /tmp/report.txt foo bar
 \end{verbatim}
 
-\code{"-v"} and \code{"{--}report"} are both options.  Assuming that
+\code{"-v"} and \code{"-{}-report"} are both options.  Assuming that
 \longprogramopt{report} takes one argument, \code{"/tmp/report.txt"} is an option
 argument.  \code{"foo"} and \code{"bar"} are positional arguments.
 
@@ -287,12 +287,12 @@
 \method{parse{\_}args()} returns two values:
 \begin{itemize}
 \item {} 
-\var{options}, an object containing values for all of your options{---}e.g. if \code{"-{}-file"} takes a single string argument, then
-\var{options.file} will be the filename supplied by the user, or
+\code{options}, an object containing values for all of your options{---}e.g. if \code{"-{}-file"} takes a single string argument, then
+\code{options.file} will be the filename supplied by the user, or
 \code{None} if the user did not supply that option
 
 \item {} 
-\var{args}, the list of positional arguments leftover after parsing
+\code{args}, the list of positional arguments leftover after parsing
 options
 
 \end{itemize}
@@ -309,7 +309,7 @@
 adding new actions is an advanced topic covered in section~\ref{optparse-extending}, Extending \module{optparse}.
 Most actions tell \module{optparse} to store a value in some variable{---}for
 example, take a string from the command line and store it in an
-attribute of \var{options}.
+attribute of \code{options}.
 
 If you don't specify an option action, \module{optparse} defaults to \code{store}.
 
@@ -333,8 +333,8 @@
 \end{verbatim}
 
 When \module{optparse} sees the option string \code{"-f"}, it consumes the next
-argument, \code{"foo.txt"}, and stores it in \var{options.filename}.  So,
-after this call to \method{parse{\_}args()}, \var{options.filename} is
+argument, \code{"foo.txt"}, and stores it in \code{options.filename}.  So,
+after this call to \method{parse{\_}args()}, \code{options.filename} is
 \code{"foo.txt"}.
 
 Some other option types supported by \module{optparse} are \code{int} and \code{float}.
@@ -379,7 +379,7 @@
 Flag options{---}set a variable to true or false when a particular option
 is seen{---}are quite common.  \module{optparse} supports them with two separate
 actions, \code{store{\_}true} and \code{store{\_}false}.  For example, you might have a
-\var{verbose} flag that is turned on with \code{"-v"} and off with \code{"-q"}:
+\code{verbose} flag that is turned on with \code{"-v"} and off with \code{"-q"}:
 \begin{verbatim}
 parser.add_option("-v", action="store_true", dest="verbose")
 parser.add_option("-q", action="store_false", dest="verbose")
@@ -421,7 +421,7 @@
 destination, which is assigned before the command line is parsed.
 
 First, consider the verbose/quiet example.  If we want \module{optparse} to set
-\var{verbose} to \code{True} unless \code{"-q"} is seen, then we can do this:
+\code{verbose} to \code{True} unless \code{"-q"} is seen, then we can do this:
 \begin{verbatim}
 parser.add_option("-v", action="store_true", dest="verbose", default=True)
 parser.add_option("-q", action="store_false", dest="verbose")
@@ -441,7 +441,7 @@
 parser.add_option("-q", action="store_false", dest="verbose", default=True)
 \end{verbatim}
 
-Again, the default value for \var{verbose} will be \code{True}: the last
+Again, the default value for \code{verbose} will be \code{True}: the last
 default value supplied for any particular destination is the one that
 counts.
 
@@ -566,7 +566,7 @@
 parser = OptionParser(usage="%prog [-f] [-q]", version="%prog 1.0")
 \end{verbatim}
 
-Note that \code{"{\%}prog"} is expanded just like it is in \var{usage}.  Apart
+Note that \code{"{\%}prog"} is expanded just like it is in \code{usage}.  Apart
 from that, \code{version} can contain anything you like.  When you supply
 it, \module{optparse} automatically adds a \code{"-{}-version"} option to your parser.
 If it encounters this option on the command line, it expands your
@@ -580,14 +580,14 @@
 \end{verbatim}
 
 
-\subsubsection{How \module{optparse} handles errors\label{optparse-how-optik-handles-errors}}
+\subsubsection{How \module{optparse} handles errors\label{optparse-how-optparse-handles-errors}}
 
 There are two broad classes of errors that \module{optparse} has to worry about:
 programmer errors and user errors.  Programmer errors are usually
-erroneous calls to \code{parse.add{\_}option()}, e.g. invalid option strings,
+erroneous calls to \code{parser.add{\_}option()}, e.g. invalid option strings,
 unknown option attributes, missing option attributes, etc.  These are
 dealt with in the usual way: raise an exception (either
-\exception{optparse.OptionError} or \exception{TypeError}) and let the program crash.
+\code{optparse.OptionError} or \code{TypeError}) and let the program crash.
 
 Handling user errors is much more important, since they are guaranteed
 to happen no matter how stable your code is.  \module{optparse} can automatically
@@ -659,12 +659,66 @@
 if __name__ == "__main__":
     main()
 \end{verbatim}
-% $Id: tutorial.txt 415 2004-09-30 02:26:17Z greg $ 
+% $Id: tutorial.txt 505 2005-07-22 01:52:40Z gward $ 
 
 
 \subsection{Reference Guide\label{optparse-reference-guide}}
 
 
+\subsubsection{Creating the parser\label{optparse-creating-parser}}
+
+The first step in using \module{optparse} is to create an OptionParser instance:
+\begin{verbatim}
+parser = OptionParser(...)
+\end{verbatim}
+
+The OptionParser constructor has no required arguments, but a number of
+optional keyword arguments.  You should always pass them as keyword
+arguments, i.e. do not rely on the order in which the arguments are
+declared.
+\begin{quote}
+\begin{description}
+\item[\code{usage} (default: \code{"{\%}prog {[}options]"})]
+The usage summary to print when your program is run incorrectly or
+with a help option.  When \module{optparse} prints the usage string, it expands
+\code{{\%}prog} to \code{os.path.basename(sys.argv{[}0])} (or to \code{prog} if
+you passed that keyword argument).  To suppress a usage message,
+pass the special value \code{optparse.SUPPRESS{\_}USAGE}.
+\item[\code{option{\_}list} (default: \code{{[}]})]
+A list of Option objects to populate the parser with.  The options
+in \code{option{\_}list} are added after any options in
+\code{standard{\_}option{\_}list} (a class attribute that may be set by
+OptionParser subclasses), but before any version or help options.
+Deprecated; use \method{add{\_}option()} after creating the parser instead.
+\item[\code{option{\_}class} (default: optparse.Option)]
+Class to use when adding options to the parser in \method{add{\_}option()}.
+\item[\code{version} (default: \code{None})]
+A version string to print when the user supplies a version option.
+If you supply a true value for \code{version}, \module{optparse} automatically adds
+a version option with the single option string \code{"-{}-version"}.  The
+substring \code{"{\%}prog"} is expanded the same as for \code{usage}.
+\item[\code{conflict{\_}handler} (default: \code{"error"})]
+Specifies what to do when options with conflicting option strings
+are added to the parser; see section~\ref{optparse-conflicts-between-options}, Conflicts between options.
+\item[\code{description} (default: \code{None})]
+A paragraph of text giving a brief overview of your program.  \module{optparse}
+reformats this paragraph to fit the current terminal width and
+prints it when the user requests help (after \code{usage}, but before
+the list of options).
+\item[\code{formatter} (default: a new IndentedHelpFormatter)]
+An instance of optparse.HelpFormatter that will be used for
+printing help text.  \module{optparse} provides two concrete classes for this
+purpose: IndentedHelpFormatter and TitledHelpFormatter.
+\item[\code{add{\_}help{\_}option} (default: \code{True})]
+If true, \module{optparse} will add a help option (with option strings \code{"-h"}
+and \code{"-{}-help"}) to the parser.
+\item[\code{prog}]
+The string to use when expanding \code{"{\%}prog"} in \code{usage} and
+\code{version} instead of \code{os.path.basename(sys.argv{[}0])}.
+\end{description}
+\end{quote}
+
+
 \subsubsection{Populating the parser\label{optparse-populating-parser}}
 
 There are several ways to populate the parser with options.  The
@@ -708,38 +762,34 @@
 specify any number of short or long option strings, but you must specify
 at least one overall option string.
 
-The canonical way to create an Option instance is by calling
-\function{make{\_}option()}, so that is what will be shown here.  However, the
-most common and convenient way is to use \code{parser.add{\_}option()}.  Note
-that \function{make{\_}option()} and \code{parser.add{\_}option()} have identical call
-signatures:
+The canonical way to create an Option instance is with the
+\method{add{\_}option()} method of \class{OptionParser}:
 \begin{verbatim}
-make_option(opt_str, ..., attr=value, ...)
-parser.add_option(opt_str, ..., attr=value, ...)
+parser.add_option(opt_str[, ...], attr=value, ...)
 \end{verbatim}
 
 To define an option with only a short option string:
 \begin{verbatim}
-make_option("-f", attr=value, ...)
+parser.add_option("-f", attr=value, ...)
 \end{verbatim}
 
 And to define an option with only a long option string:
 \begin{verbatim}
-make_option("--foo", attr=value, ...)
+parser.add_option("--foo", attr=value, ...)
 \end{verbatim}
 
-The \code{attr=value} keyword arguments define option attributes,
-i.e. attributes of the Option object.  The most important option
-attribute is \member{action}, and it largely determines what other attributes
-are relevant or required.  If you pass irrelevant option attributes, or
-fail to pass required ones, \module{optparse} raises an OptionError exception
-explaining your mistake.
-
-An options's \emph{action} determines what \module{optparse} does when it encounters
-this option on the command-line.  The actions hard-coded into \module{optparse} are:
+The keyword arguments define attributes of the new Option object.  The
+most important option attribute is \member{action}, and it largely determines
+which other attributes are relevant or required.  If you pass irrelevant
+option attributes, or fail to pass required ones, \module{optparse} raises an
+OptionError exception explaining your mistake.
+
+An options's \emph{action} determines what \module{optparse} does when it encounters this
+option on the command-line.  The standard option actions hard-coded into
+\module{optparse} are:
 \begin{description}
 \item[\code{store}]
-store this option's argument {[}default]
+store this option's argument (default)
 \item[\code{store{\_}const}]
 store a constant value
 \item[\code{store{\_}true}]
@@ -748,6 +798,8 @@
 store a false value
 \item[\code{append}]
 append this option's argument to a list
+\item[\code{append{\_}const}]
+append a constant value to a list
 \item[\code{count}]
 increment a counter by one
 \item[\code{callback}]
@@ -762,24 +814,25 @@
 below.)
 
 As you can see, most actions involve storing or updating a value
-somewhere.  \module{optparse} always creates an instance of \code{optparse.Values}
-specifically for this purpose; we refer to this instance as \var{options}.
-Option arguments (and various other values) are stored as attributes of
-this object, according to the \member{dest} (destination) option attribute.
+somewhere.  \module{optparse} always creates a special object for this,
+conventionally called \code{options} (it happens to be an instance of
+\code{optparse.Values}).  Option arguments (and various other values) are
+stored as attributes of this object, according to the \member{dest}
+(destination) option attribute.
 
 For example, when you call
 \begin{verbatim}
 parser.parse_args()
 \end{verbatim}
 
-one of the first things \module{optparse} does is create the \var{options} object:
+one of the first things \module{optparse} does is create the \code{options} object:
 \begin{verbatim}
 options = Values()
 \end{verbatim}
 
 If one of the options in this parser is defined with
 \begin{verbatim}
-make_option("-f", "--file", action="store", type="string", dest="filename")
+parser.add_option("-f", "--file", action="store", type="string", dest="filename")
 \end{verbatim}
 
 and the command-line being parsed includes any of the following:
@@ -790,8 +843,7 @@
 --file foo
 \end{verbatim}
 
-then \module{optparse}, on seeing the \programopt{-f} or \longprogramopt{file} option, will do the
-equivalent of
+then \module{optparse}, on seeing this option, will do the equivalent of
 \begin{verbatim}
 options.filename = "foo"
 \end{verbatim}
@@ -912,6 +964,13 @@
 \end{verbatim}
 
 \item {} 
+\code{append{\_}const} {[}required: \code{const}; relevant: \member{dest}]
+
+Like \code{store{\_}const}, but the value \code{const} is appended to \member{dest};
+as with \code{append}, \member{dest} defaults to \code{None}, and an an empty list is
+automatically created the first time the option is encountered.
+
+\item {} 
 \code{count} {[}relevant: \member{dest}]
 
 Increment the integer stored at \member{dest}.  If no default value is
@@ -939,14 +998,9 @@
 \code{callback} {[}required: \code{callback};
 relevant: \member{type}, \code{nargs}, \code{callback{\_}args}, \code{callback{\_}kwargs}]
 
-Call the function specified by \code{callback}.  The signature of
-this function should be
+Call the function specified by \code{callback}, which is called as
 \begin{verbatim}
-func(option : Option,
-     opt : string,
-     value : any,
-     parser : OptionParser,
-     *args, **kwargs)
+func(option, opt_str, value, parser, *args, **kwargs)
 \end{verbatim}
 
 See section~\ref{optparse-option-callbacks}, Option Callbacks for more detail.
@@ -956,7 +1010,7 @@
 
 Prints a complete help message for all the options in the
 current option parser.  The help message is constructed from
-the \var{usage} string passed to OptionParser's constructor and
+the \code{usage} string passed to OptionParser's constructor and
 the \member{help} string passed to every option.
 
 If no \member{help} string is supplied for an option, it will still be
@@ -1007,6 +1061,87 @@
 \end{itemize}
 
 
+\subsubsection{Option attributes\label{optparse-option-attributes}}
+
+The following option attributes may be passed as keyword arguments
+to \code{parser.add{\_}option()}.  If you pass an option attribute
+that is not relevant to a particular option, or fail to pass a required
+option attribute, \module{optparse} raises OptionError.
+\begin{itemize}
+\item {} 
+\member{action} (default: \code{"store"})
+
+Determines \module{optparse}'s behaviour when this option is seen on the command
+line; the available options are documented above.
+
+\item {} 
+\member{type} (default: \code{"string"})
+
+The argument type expected by this option (e.g., \code{"string"} or
+\code{"int"}); the available option types are documented below.
+
+\item {} 
+\member{dest} (default: derived from option strings)
+
+If the option's action implies writing or modifying a value somewhere,
+this tells \module{optparse} where to write it: \member{dest} names an attribute of the
+\code{options} object that \module{optparse} builds as it parses the command line.
+
+\item {} 
+\code{default} (deprecated)
+
+The value to use for this option's destination if the option is not
+seen on the command line.  Deprecated; use \code{parser.set{\_}defaults()}
+instead.
+
+\item {} 
+\code{nargs} (default: 1)
+
+How many arguments of type \member{type} should be consumed when this
+option is seen.  If {\textgreater} 1, \module{optparse} will store a tuple of values to
+\member{dest}.
+
+\item {} 
+\code{const}
+
+For actions that store a constant value, the constant value to store.
+
+\item {} 
+\code{choices}
+
+For options of type \code{"choice"}, the list of strings the user
+may choose from.
+
+\item {} 
+\code{callback}
+
+For options with action \code{"callback"}, the callable to call when this
+option is seen.  See section~\ref{optparse-option-callbacks}, Option Callbacks for detail on the arguments
+passed to \code{callable}.
+
+\item {} 
+\code{callback{\_}args}, \code{callback{\_}kwargs}
+
+Additional positional and keyword arguments to pass to \code{callback}
+after the four standard callback arguments.
+
+\item {} 
+\member{help}
+
+Help text to print for this option when listing all available options
+after the user supplies a \member{help} option (such as \code{"-{}-help"}).
+If no help text is supplied, the option will be listed without help
+text.  To hide this option, use the special value \code{SUPPRESS{\_}HELP}.
+
+\item {} 
+\code{metavar} (default: derived from option strings)
+
+Stand-in for the option argument(s) to use when printing help text.
+See section~\ref{optparse-tutorial}, the tutorial for an example.
+
+\end{itemize}
+
+
 \subsubsection{Standard option types\label{optparse-standard-option-types}}
 
 \module{optparse} has six built-in option types: \code{string}, \code{int}, \code{long},
@@ -1017,22 +1152,74 @@
 text on the command line is stored in the destination (or passed to the
 callback) as-is.
 
-Integer arguments are passed to \code{int()} to convert them to Python
-integers.  If \code{int()} fails, so will \module{optparse}, although with a more
-useful error message.  (Internally, \module{optparse} raises
-\exception{OptionValueError}; OptionParser catches this exception higher
-up and terminates your program with a useful error message.)
-
-Likewise, \code{float} arguments are passed to \code{float()} for conversion,
-\code{long} arguments to \code{long()}, and \code{complex} arguments to
-\code{complex()}.  Apart from that, they are handled identically to integer
-arguments.
+Integer arguments (type \code{int} or \code{long}) are parsed as follows:
+\begin{quote}
+\begin{itemize}
+\item {} 
+if the number starts with \code{0x}, it is parsed as a hexadecimal number
+
+\item {} 
+if the number starts with \code{0}, it is parsed as an octal number
+
+\item {} 
+if the number starts with \code{0b}, is is parsed as a binary number
+
+\item {} 
+otherwise, the number is parsed as a decimal number
+
+\end{itemize}
+\end{quote}
+
+The conversion is done by calling either \code{int()} or \code{long()} with
+the appropriate base (2, 8, 10, or 16).  If this fails, so will \module{optparse},
+although with a more useful error message.
+
+\code{float} and \code{complex} option arguments are converted directly with
+\code{float()} and \code{complex()}, with similar error-handling.
 
 \code{choice} options are a subtype of \code{string} options.  The \code{choices}
 option attribute (a sequence of strings) defines the set of allowed
-option arguments.  \code{optparse.option.check{\_}choice()} compares
+option arguments.  \code{optparse.check{\_}choice()} compares
 user-supplied option arguments against this master list and raises
-\exception{OptionValueError} if an invalid string is given.
+OptionValueError if an invalid string is given.
+
+
+\subsubsection{Parsing arguments\label{optparse-parsing-arguments}}
+
+The whole point of creating and populating an OptionParser is to call
+its \method{parse{\_}args()} method:
+\begin{verbatim}
+(options, args) = parser.parse_args(args=None, options=None)
+\end{verbatim}
+
+where the input parameters are
+\begin{description}
+\item[\code{args}]
+the list of arguments to process (\code{sys.argv{[}1:]} by default)
+\item[\code{options}]
+object to store option arguments in (a new instance of
+optparse.Values by default)
+\end{description}
+
+and the return values are
+\begin{description}
+\item[\code{options}]
+the same object as was passed in as \code{options}, or the new
+optparse.Values instance created by \module{optparse}
+\item[\code{args}]
+the leftover positional arguments after all options have been
+processed
+\end{description}
+
+The most common usage is to supply neither keyword argument.  If you
+supply a \code{values} object, it will be repeatedly modified with a
+\code{setattr()} call for every option argument written to an option
+destination, and finally returned by \method{parse{\_}args()}.
+
+If \method{parse{\_}args()} encounters any errors in the argument list, it calls
+the OptionParser's \method{error()} method with an appropriate end-user error
+message.  This ultimately terminates your process with an exit status of
+2 (the traditional \UNIX{} exit status for command-line errors).
 
 
 \subsubsection{Querying and manipulating your option parser\label{optparse-querying-manipulating-option-parser}}
@@ -1050,9 +1237,8 @@
 If the OptionParser has an option corresponding to \code{opt{\_}str},
 that option is removed.  If that option provided any other
 option strings, all of those option strings become invalid.
-
 If \code{opt{\_}str} does not occur in any option belonging to this
-OptionParser, raises \exception{ValueError}.
+OptionParser, raises ValueError.
 \end{description}
 
 
@@ -1074,20 +1260,20 @@
 mechanism.  You can set the conflict-handling mechanism either in the
 constructor:
 \begin{verbatim}
-parser = OptionParser(..., conflict_handler="...")
+parser = OptionParser(..., conflict_handler=handler)
 \end{verbatim}
 
 or with a separate call:
 \begin{verbatim}
-parser.set_conflict_handler("...")
+parser.set_conflict_handler(handler)
 \end{verbatim}
 
-The available conflict-handling mechanisms are:
+The available conflict handlers are:
 \begin{quote}
 \begin{description}
 \item[\code{error} (default)]
 assume option conflicts are a programming error and raise 
-\exception{OptionConflictError}
+OptionConflictError
 \item[\code{resolve}]
 resolve option conflicts intelligently (see below)
 \end{description}
@@ -1131,7 +1317,78 @@
   -n, --noisy   be noisy
   --dry-run     new dry-run option
 \end{verbatim}
-% $Id: reference.txt 415 2004-09-30 02:26:17Z greg $ 
+
+
+\subsubsection{Cleanup\label{optparse-cleanup}}
+
+OptionParser instances have several cyclic references.  This should not
+be a problem for Python's garbage collector, but you may wish to break
+the cyclic references explicitly by calling \code{destroy()} on your
+OptionParser once you are done with it.  This is particularly useful in
+long-running applications where large object graphs are reachable from
+your OptionParser.
+
+
+\subsubsection{Other methods\label{optparse-other-methods}}
+
+OptionParser supports several other public methods:
+\begin{itemize}
+\item {} 
+\code{set{\_}usage(usage)}
+
+Set the usage string according to the rules described above for the
+\code{usage} constructor keyword argument.  Passing \code{None} sets the
+default usage string; use \code{SUPPRESS{\_}USAGE} to suppress a usage
+message.
+
+\item {} 
+\code{enable{\_}interspersed{\_}args()}, \code{disable{\_}interspersed{\_}args()}
+
+Enable/disable positional arguments interspersed with options, similar
+to GNU getopt (enabled by default).  For example, if \code{"-a"} and
+\code{"-b"} are both simple options that take no arguments, \module{optparse}
+normally accepts this syntax:
+\begin{verbatim}
+prog -a arg1 -b arg2
+\end{verbatim}
+
+and treats it as equivalent to
+\begin{verbatim}
+prog -a -b arg1 arg2
+\end{verbatim}
+
+To disable this feature, call \code{disable{\_}interspersed{\_}args()}.  This
+restores traditional \UNIX{} syntax, where option parsing stops with the
+first non-option argument.
+
+\item {} 
+\code{set{\_}defaults(dest=value, ...)}
+
+Set default values for several option destinations at once.  Using
+\method{set{\_}defaults()} is the preferred way to set default values for
+options, since multiple options can share the same destination.  For
+example, if several ``mode'' options all set the same destination, any
+one of them can set the default, and the last one wins:
+\begin{verbatim}
+parser.add_option("--advanced", action="store_const",
+                  dest="mode", const="advanced",
+                  default="novice")    # overridden below
+parser.add_option("--novice", action="store_const",
+                  dest="mode", const="novice",
+                  default="advanced")  # overrides above setting
+\end{verbatim}
+
+To avoid this confusion, use \method{set{\_}defaults()}:
+\begin{verbatim}
+parser.set_defaults(mode="advanced")
+parser.add_option("--advanced", action="store_const",
+                  dest="mode", const="advanced")
+parser.add_option("--novice", action="store_const",
+                  dest="mode", const="novice")
+\end{verbatim}
+
+\end{itemize}
+% $Id: reference.txt 505 2005-07-22 01:52:40Z gward $ 
 
 
 \subsection{Option Callbacks\label{optparse-option-callbacks}}
@@ -1234,7 +1491,7 @@
 the current list of leftover arguments, ie. arguments that have
 been consumed but are neither options nor option arguments.
 Feel free to modify \code{parser.largs}, e.g. by adding more
-arguments to it.  (This list will become \var{args}, the second
+arguments to it.  (This list will become \code{args}, the second
 return value of \method{parse{\_}args()}.)
 \item[\code{parser.rargs}]
 the current list of remaining arguments, ie. with \code{opt{\_}str} and
@@ -1260,7 +1517,7 @@
 
 \subsubsection{Raising errors in a callback\label{optparse-raising-errors-in-callback}}
 
-The callback function should raise \exception{OptionValueError} if there are any
+The callback function should raise OptionValueError if there are any
 problems with the option or its argument(s).  \module{optparse} catches this and
 terminates the program, printing the error message you supply to
 stderr.  Your message should be clear, concise, accurate, and mention

Modified: python/trunk/Lib/optparse.py
==============================================================================
--- python/trunk/Lib/optparse.py	(original)
+++ python/trunk/Lib/optparse.py	Sun Apr 23 05:47:58 2006
@@ -16,7 +16,7 @@
 # Python developers: please do not make changes to this file, since
 # it is automatically generated from the Optik source code.
 
-__version__ = "1.5a2"
+__version__ = "1.5.1"
 
 __all__ = ['Option',
            'SUPPRESS_HELP',
@@ -35,8 +35,8 @@
            'BadOptionError']
 
 __copyright__ = """
-Copyright (c) 2001-2004 Gregory P. Ward.  All rights reserved.
-Copyright (c) 2002-2004 Python Software Foundation.  All rights reserved.
+Copyright (c) 2001-2006 Gregory P. Ward.  All rights reserved.
+Copyright (c) 2002-2006 Python Software Foundation.  All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
@@ -67,21 +67,26 @@
 """
 
 import sys, os
+import types
 import textwrap
-try:
-    from gettext import gettext as _
-except ImportError:
-    _ = lambda arg: arg
 
 def _repr(self):
     return "<%s at 0x%x: %s>" % (self.__class__.__name__, id(self), self)
 
 
 # This file was generated from:
-#   Id: option_parser.py 421 2004-10-26 00:45:16Z greg
-#   Id: option.py 422 2004-10-26 00:53:47Z greg
-#   Id: help.py 367 2004-07-24 23:21:21Z gward
-#   Id: errors.py 367 2004-07-24 23:21:21Z gward
+#   Id: option_parser.py 509 2006-04-20 00:58:24Z gward
+#   Id: option.py 509 2006-04-20 00:58:24Z gward
+#   Id: help.py 509 2006-04-20 00:58:24Z gward
+#   Id: errors.py 509 2006-04-20 00:58:24Z gward
+
+try:
+    from gettext import gettext
+except ImportError:
+    def gettext(message):
+        return message
+_ = gettext
+
 
 class OptParseError (Exception):
     def __init__(self, msg):
@@ -120,8 +125,25 @@
 
 class BadOptionError (OptParseError):
     """
-    Raised if an invalid or ambiguous option is seen on the command-line.
+    Raised if an invalid option is seen on the command line.
     """
+    def __init__(self, opt_str):
+        self.opt_str = opt_str
+
+    def __str__(self):
+        return _("no such option: %s") % self.opt_str
+
+class AmbiguousOptionError (BadOptionError):
+    """
+    Raised if an ambiguous option is seen on the command line.
+    """
+    def __init__(self, opt_str, possibilities):
+        BadOptionError.__init__(self, opt_str)
+        self.possibilities = possibilities
+
+    def __str__(self):
+        return (_("ambiguous option: %s (%s?)")
+                % (self.opt_str, ", ".join(self.possibilities)))
 
 
 class HelpFormatter:
@@ -223,15 +245,30 @@
     def format_heading(self, heading):
         raise NotImplementedError, "subclasses must implement"
 
-    def format_description(self, description):
-        if not description:
-            return ""
-        desc_width = self.width - self.current_indent
+    def _format_text(self, text):
+        """
+        Format a paragraph of free-form text for inclusion in the
+        help output at the current indentation level.
+        """
+        text_width = self.width - self.current_indent
         indent = " "*self.current_indent
-        return textwrap.fill(description,
-                             desc_width,
+        return textwrap.fill(text,
+                             text_width,
                              initial_indent=indent,
-                             subsequent_indent=indent) + "\n"
+                             subsequent_indent=indent)
+        
+    def format_description(self, description):
+        if description:
+            return self._format_text(description) + "\n"
+        else:
+            return ""
+
+    def format_epilog(self, epilog):
+        if epilog:
+            return "\n" + self._format_text(epilog) + "\n"
+        else:
+            return ""
+
 
     def expand_default(self, option):
         if self.parser is None or not self.default_tag:
@@ -328,7 +365,7 @@
             self, indent_increment, max_help_position, width, short_first)
 
     def format_usage(self, usage):
-        return _("usage: %s\n") % usage
+        return _("Usage: %s\n") % usage
 
     def format_heading(self, heading):
         return "%*s%s:\n" % (self.current_indent, "", heading)
@@ -353,8 +390,27 @@
         return "%s\n%s\n" % (heading, "=-"[self.level] * len(heading))
 
 
-_builtin_cvt = { "int" : (int, _("integer")),
-                 "long" : (long, _("long integer")),
+def _parse_num(val, type):
+    if val[:2].lower() == "0x":         # hexadecimal
+        radix = 16
+    elif val[:2].lower() == "0b":       # binary
+        radix = 2
+        val = val[2:] or "0"            # have to remove "0b" prefix
+    elif val[:1] == "0":                # octal
+        radix = 8
+    else:                               # decimal
+        radix = 10
+
+    return type(val, radix)
+
+def _parse_int(val):
+    return _parse_num(val, int)
+
+def _parse_long(val):
+    return _parse_num(val, long)
+
+_builtin_cvt = { "int" : (_parse_int, _("integer")),
+                 "long" : (_parse_long, _("long integer")),
                  "float" : (float, _("floating-point")),
                  "complex" : (complex, _("complex")) }
 
@@ -422,6 +478,7 @@
                "store_true",
                "store_false",
                "append",
+               "append_const",
                "count",
                "callback",
                "help",
@@ -435,6 +492,7 @@
                      "store_true",
                      "store_false",
                      "append",
+                     "append_const",
                      "count")
 
     # The set of actions for which it makes sense to supply a value
@@ -448,6 +506,10 @@
     ALWAYS_TYPED_ACTIONS = ("store",
                             "append")
 
+    # The set of actions which take a 'const' attribute.
+    CONST_ACTIONS = ("store_const",
+                     "append_const")
+
     # The set of known types for option parsers.  Again, listed here for
     # constructor argument validation.
     TYPES = ("string", "int", "long", "float", "complex", "choice")
@@ -572,9 +634,17 @@
                     # No type given?  "string" is the most sensible default.
                     self.type = "string"
         else:
-            # Allow type objects as an alternative to their names.
-            if type(self.type) is type:
+            # Allow type objects or builtin type conversion functions
+            # (int, str, etc.) as an alternative to their names.  (The
+            # complicated check of __builtin__ is only necessary for
+            # Python 2.1 and earlier, and is short-circuited by the
+            # first check on modern Pythons.)
+            import __builtin__
+            if ( type(self.type) is types.TypeType or
+                 (hasattr(self.type, "__name__") and
+                  getattr(__builtin__, self.type.__name__, None) is self.type) ):
                 self.type = self.type.__name__
+
             if self.type == "str":
                 self.type = "string"
 
@@ -589,7 +659,7 @@
             if self.choices is None:
                 raise OptionError(
                     "must supply a list of choices for type 'choice'", self)
-            elif type(self.choices) not in (tuple, list):
+            elif type(self.choices) not in (types.TupleType, types.ListType):
                 raise OptionError(
                     "choices must be a list of strings ('%s' supplied)"
                     % str(type(self.choices)).split("'")[1], self)
@@ -613,7 +683,7 @@
                 self.dest = self._short_opts[0][1]
 
     def _check_const(self):
-        if self.action != "store_const" and self.const is not None:
+        if self.action not in self.CONST_ACTIONS and self.const is not None:
             raise OptionError(
                 "'const' must not be supplied for action %r" % self.action,
                 self)
@@ -633,12 +703,12 @@
                 raise OptionError(
                     "callback not callable: %r" % self.callback, self)
             if (self.callback_args is not None and
-                type(self.callback_args) is not tuple):
+                type(self.callback_args) is not types.TupleType):
                 raise OptionError(
                     "callback_args, if supplied, must be a tuple: not %r"
                     % self.callback_args, self)
             if (self.callback_kwargs is not None and
-                type(self.callback_kwargs) is not dict):
+                type(self.callback_kwargs) is not types.DictType):
                 raise OptionError(
                     "callback_kwargs, if supplied, must be a dict: not %r"
                     % self.callback_kwargs, self)
@@ -720,6 +790,8 @@
             setattr(values, dest, False)
         elif action == "append":
             values.ensure_value(dest, []).append(value)
+        elif action == "append_const":
+            values.ensure_value(dest, []).append(self.const)
         elif action == "count":
             setattr(values, dest, values.ensure_value(dest, 0) + 1)
         elif action == "callback":
@@ -748,11 +820,9 @@
     True, False
 except NameError:
     (True, False) = (1, 0)
-try:
-    basestring
-except NameError:
-    basestring = (str, unicode)
 
+def isbasestring(x):
+    return isinstance(x, types.StringType) or isinstance(x, types.UnicodeType)
 
 class Values:
 
@@ -766,16 +836,13 @@
 
     __repr__ = _repr
 
-    def __eq__(self, other):
+    def __cmp__(self, other):
         if isinstance(other, Values):
-            return self.__dict__ == other.__dict__
-        elif isinstance(other, dict):
-            return self.__dict__ == other
+            return cmp(self.__dict__, other.__dict__)
+        elif isinstance(other, types.DictType):
+            return cmp(self.__dict__, other)
         else:
-            return False
-
-    def __ne__(self, other):
-        return not (self == other)
+            return -1
 
     def _update_careful(self, dict):
         """
@@ -893,6 +960,13 @@
         return self.description
 
 
+    def destroy(self):
+        """see OptionParser.destroy()."""
+        del self._short_opt
+        del self._long_opt
+        del self.defaults
+
+
     # -- Option-adding methods -----------------------------------------
 
     def _check_conflict(self, option):
@@ -926,7 +1000,7 @@
         """add_option(Option)
            add_option(opt_str, ..., kwarg=val, ...)
         """
-        if type(args[0]) is str:
+        if type(args[0]) is types.StringType:
             option = self.option_class(*args, **kwargs)
         elif len(args) == 1 and not kwargs:
             option = args[0]
@@ -1018,6 +1092,11 @@
     def set_title(self, title):
         self.title = title
 
+    def destroy(self):
+        """see OptionParser.destroy()."""
+        OptionContainer.destroy(self)
+        del self.option_list
+
     # -- Help-formatting methods ---------------------------------------
 
     def format_help(self, formatter):
@@ -1044,6 +1123,8 @@
       prog : string
         the name of the current program (to override
         os.path.basename(sys.argv[0])).
+      epilog : string
+        paragraph of help text to print after option help
 
       option_groups : [OptionGroup]
         list of option groups in this parser (option groups are
@@ -1102,7 +1183,8 @@
                  description=None,
                  formatter=None,
                  add_help_option=True,
-                 prog=None):
+                 prog=None,
+                 epilog=None):
         OptionContainer.__init__(
             self, option_class, conflict_handler, description)
         self.set_usage(usage)
@@ -1114,6 +1196,7 @@
             formatter = IndentedHelpFormatter()
         self.formatter = formatter
         self.formatter.set_parser(self)
+        self.epilog = epilog
 
         # Populate the option list; initial sources are the
         # standard_option_list class attribute, the 'option_list'
@@ -1124,6 +1207,22 @@
 
         self._init_parsing_state()
 
+
+    def destroy(self):
+        """
+        Declare that you are done with this OptionParser.  This cleans up
+        reference cycles so the OptionParser (and all objects referenced by
+        it) can be garbage-collected promptly.  After calling destroy(), the 
+        OptionParser is unusable.
+        """
+        OptionContainer.destroy(self)
+        for group in self.option_groups:
+            group.destroy()
+        del self.option_list
+        del self.option_groups
+        del self.formatter
+
+
     # -- Private methods -----------------------------------------------
     # (used by our or OptionContainer's constructor)
 
@@ -1167,7 +1266,7 @@
         elif usage is SUPPRESS_USAGE:
             self.usage = None
         # For backwards compatibility with Optik 1.3 and earlier.
-        elif usage.startswith("usage:" + " "):
+        elif usage.lower().startswith("usage: "):
             self.usage = usage[7:]
         else:
             self.usage = usage
@@ -1201,7 +1300,7 @@
         defaults = self.defaults.copy()
         for option in self._get_all_options():
             default = defaults.get(option.dest)
-            if isinstance(default, basestring):
+            if isbasestring(default):
                 opt_str = option.get_opt_string()
                 defaults[option.dest] = option.check_value(opt_str, default)
 
@@ -1212,7 +1311,7 @@
 
     def add_option_group(self, *args, **kwargs):
         # XXX lots of overlap with OptionContainer.add_option()
-        if type(args[0]) is str:
+        if type(args[0]) is types.StringType:
             group = OptionGroup(self, *args, **kwargs)
         elif len(args) == 1 and not kwargs:
             group = args[0]
@@ -1276,7 +1375,7 @@
         try:
             stop = self._process_args(largs, rargs, values)
         except (BadOptionError, OptionValueError), err:
-            self.error(err.msg)
+            self.error(str(err))
 
         args = largs + rargs
         return self.check_values(values, args)
@@ -1401,7 +1500,7 @@
             i += 1                      # we have consumed a character
 
             if not option:
-                self.error(_("no such option: %s") % opt)
+                raise BadOptionError(opt)
             if option.takes_value():
                 # Any characters left in arg?  Pretend they're the
                 # next arg, and stop consuming characters of arg.
@@ -1501,7 +1600,7 @@
             formatter = self.formatter
         formatter.store_option_strings(self)
         result = []
-        result.append(formatter.format_heading(_("options")))
+        result.append(formatter.format_heading(_("Options")))
         formatter.indent()
         if self.option_list:
             result.append(OptionContainer.format_option_help(self, formatter))
@@ -1513,6 +1612,9 @@
         # Drop the last "\n", or the header if no options or option groups:
         return "".join(result[:-1])
 
+    def format_epilog(self, formatter):
+        return formatter.format_epilog(self.epilog)
+
     def format_help(self, formatter=None):
         if formatter is None:
             formatter = self.formatter
@@ -1522,6 +1624,7 @@
         if self.description:
             result.append(self.format_description(formatter) + "\n")
         result.append(self.format_option_help(formatter))
+        result.append(self.format_epilog(formatter))
         return "".join(result)
 
     def print_help(self, file=None):
@@ -1555,11 +1658,10 @@
         if len(possibilities) == 1:
             return possibilities[0]
         elif not possibilities:
-            raise BadOptionError(_("no such option: %s") % s)
+            raise BadOptionError(s)
         else:
             # More than one possible completion: ambiguous prefix.
-            raise BadOptionError(_("ambiguous option: %s (%s?)")
-                                 % (s, ", ".join(possibilities)))
+            raise AmbiguousOptionError(s, possibilities)
 
 
 # Some day, there might be many Option classes.  As of Optik 1.3, the

Modified: python/trunk/Lib/test/test_optparse.py
==============================================================================
--- python/trunk/Lib/test/test_optparse.py	(original)
+++ python/trunk/Lib/test/test_optparse.py	Sun Apr 23 05:47:58 2006
@@ -10,17 +10,22 @@
 
 import sys
 import os
+import re
 import copy
+import types
 import unittest
 
 from cStringIO import StringIO
 from pprint import pprint
 from test import test_support
 
+
 from optparse import make_option, Option, IndentedHelpFormatter, \
      TitledHelpFormatter, OptionParser, OptionContainer, OptionGroup, \
      SUPPRESS_HELP, SUPPRESS_USAGE, OptionError, OptionConflictError, \
-     BadOptionError, OptionValueError, Values, _match_abbrev
+     BadOptionError, OptionValueError, Values
+from optparse import _match_abbrev
+from optparse import _parse_num
 
 # Do the right thing with boolean values for all known Python versions.
 try:
@@ -28,6 +33,7 @@
 except NameError:
     (True, False) = (1, 0)
 
+retype = type(re.compile(''))
 
 class InterceptedError(Exception):
     def __init__(self,
@@ -96,7 +102,8 @@
           args -- positional arguments to `func`
           kwargs -- keyword arguments to `func`
           expected_exception -- exception that should be raised
-          expected_output -- output we expect to see
+          expected_message -- expected exception message (or pattern
+            if a compiled regex object)
 
         Returns the exception raised for further testing.
         """
@@ -109,14 +116,23 @@
             func(*args, **kwargs)
         except expected_exception, err:
             actual_message = str(err)
-            self.assertEqual(actual_message,
-                             expected_message,
+            if isinstance(expected_message, retype):
+                self.assert_(expected_message.search(actual_message),
                              """\
+expected exception message pattern:
+/%s/
+actual exception message:
+'''%s'''
+""" % (expected_message.pattern, actual_message))
+            else:
+                self.assertEqual(actual_message,
+                                 expected_message,
+                                 """\
 expected exception message:
-'''%(expected_message)s'''
+'''%s'''
 actual exception message:
-'''%(actual_message)s'''
-""" % locals())
+'''%s'''
+""" % (expected_message, actual_message))
 
             return err
         else:
@@ -157,7 +173,9 @@
                 sys.stdout = save_stdout
 
         except InterceptedError, err:
-            self.assertEqual(output, expected_output)
+            if output != expected_output:
+                self.fail("expected: \n'''\n" + expected_output +
+                          "'''\nbut got \n'''\n" + output + "'''")
             self.assertEqual(err.exit_status, expected_status)
             self.assertEqual(err.exit_message, expected_error)
         else:
@@ -366,6 +384,23 @@
         self.assertRaises(self.parser.remove_option, ('foo',), None,
                           ValueError, "no such option 'foo'")
 
+    def test_refleak(self):
+        # If an OptionParser is carrying around a reference to a large
+        # object, various cycles can prevent it from being GC'd in
+        # a timely fashion.  destroy() breaks the cycles to ensure stuff
+        # can be cleaned up.
+        big_thing = [42]
+        refcount = sys.getrefcount(big_thing)
+        parser = OptionParser()
+        parser.add_option("-a", "--aaarggh")
+        parser.big_thing = big_thing
+
+        parser.destroy()
+        #self.assertEqual(refcount, sys.getrefcount(big_thing))
+        del parser
+        self.assertEqual(refcount, sys.getrefcount(big_thing))
+
+
 class TestOptionValues(BaseTest):
     def setUp(self):
         pass
@@ -391,13 +426,21 @@
     def setUp(self):
         self.parser = OptionParser()
 
-    def test_type_aliases(self):
-        self.parser.add_option("-x", type=int)
+    def test_str_aliases_string(self):
+        self.parser.add_option("-s", type="str")
+        self.assertEquals(self.parser.get_option("-s").type, "string")
+
+    def test_new_type_object(self):
         self.parser.add_option("-s", type=str)
-        self.parser.add_option("-t", type="str")
+        self.assertEquals(self.parser.get_option("-s").type, "string")
+        self.parser.add_option("-x", type=int)
         self.assertEquals(self.parser.get_option("-x").type, "int")
+
+    def test_old_type_object(self):
+        self.parser.add_option("-s", type=types.StringType)
         self.assertEquals(self.parser.get_option("-s").type, "string")
-        self.assertEquals(self.parser.get_option("-t").type, "string")
+        self.parser.add_option("-x", type=types.IntType)
+        self.assertEquals(self.parser.get_option("-x").type, "int")
 
 
 # Custom type for testing processing of default values.
@@ -487,13 +530,13 @@
         save_argv = sys.argv[:]
         try:
             sys.argv[0] = os.path.join("foo", "bar", "baz.py")
-            parser = OptionParser("usage: %prog ...", version="%prog 1.2")
-            expected_usage = "usage: baz.py ...\n"
+            parser = OptionParser("%prog ...", version="%prog 1.2")
+            expected_usage = "Usage: baz.py ...\n"
             self.assertUsage(parser, expected_usage)
             self.assertVersion(parser, "baz.py 1.2")
             self.assertHelp(parser,
                             expected_usage + "\n" +
-                            "options:\n"
+                            "Options:\n"
                             "  --version   show program's version number and exit\n"
                             "  -h, --help  show this help message and exit\n")
         finally:
@@ -505,7 +548,7 @@
                               usage="%prog arg arg")
         parser.remove_option("-h")
         parser.remove_option("--version")
-        expected_usage = "usage: thingy arg arg\n"
+        expected_usage = "Usage: thingy arg arg\n"
         self.assertUsage(parser, expected_usage)
         self.assertVersion(parser, "thingy 0.1")
         self.assertHelp(parser, expected_usage + "\n")
@@ -515,9 +558,9 @@
     def setUp(self):
         self.parser = OptionParser(prog="test")
         self.help_prefix = """\
-usage: test [options]
+Usage: test [options]
 
-options:
+Options:
   -h, --help            show this help message and exit
 """
         self.file_help = "read from FILE [default: %default]"
@@ -699,13 +742,16 @@
         self.assertParseOK(["-a", "--", "foo", "bar"],
                            {'a': "--", 'boo': None, 'foo': None},
                            ["foo", "bar"]),
+        self.assertParseOK(["-a", "--", "--foo", "bar"],
+                           {'a': "--", 'boo': None, 'foo': ["bar"]},
+                           []),
 
     def test_short_option_joined_and_separator(self):
         self.assertParseOK(["-ab", "--", "--foo", "bar"],
                            {'a': "b", 'boo': None, 'foo': None},
                            ["--foo", "bar"]),
 
-    def test_invalid_option_becomes_positional_arg(self):
+    def test_hyphen_becomes_positional_arg(self):
         self.assertParseOK(["-ab", "-", "--foo", "bar"],
                            {'a': "b", 'boo': None, 'foo': ["bar"]},
                            ["-"])
@@ -870,6 +916,8 @@
                                type="float", dest="point")
         self.parser.add_option("-f", "--foo", action="append", nargs=2,
                                type="int", dest="foo")
+        self.parser.add_option("-z", "--zero", action="append_const",
+                               dest="foo", const=(0, 0))
 
     def test_nargs_append(self):
         self.assertParseOK(["-f", "4", "-3", "blah", "--foo", "1", "666"],
@@ -885,6 +933,11 @@
                            {'point': None, 'foo':[(3, 4)]},
                            [])
 
+    def test_nargs_append_const(self):
+        self.assertParseOK(["--zero", "--foo", "3", "4", "-z"],
+                           {'point': None, 'foo':[(0, 0), (3, 4), (0, 0)]},
+                           [])
+
 class TestVersion(BaseTest):
     def test_version(self):
         self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
@@ -960,8 +1013,14 @@
         self.parser.add_option("-a", None, type="string", dest="a")
         self.parser.add_option("-f", "--file", type="file", dest="file")
 
+    def tearDown(self):
+        if os.path.isdir(test_support.TESTFN):
+            os.rmdir(test_support.TESTFN)
+        elif os.path.isfile(test_support.TESTFN):
+            os.unlink(test_support.TESTFN)
+
     class MyOption (Option):
-        def check_file (option, opt, value):
+        def check_file(option, opt, value):
             if not os.path.exists(value):
                 raise OptionValueError("%s: file does not exist" % value)
             elif not os.path.isfile(value):
@@ -972,25 +1031,23 @@
         TYPE_CHECKER = copy.copy(Option.TYPE_CHECKER)
         TYPE_CHECKER["file"] = check_file
 
-    def test_extend_file(self):
+    def test_filetype_ok(self):
         open(test_support.TESTFN, "w").close()
         self.assertParseOK(["--file", test_support.TESTFN, "-afoo"],
                            {'file': test_support.TESTFN, 'a': 'foo'},
                            [])
 
-        os.unlink(test_support.TESTFN)
-
-    def test_extend_file_nonexistent(self):
+    def test_filetype_noexist(self):
         self.assertParseFail(["--file", test_support.TESTFN, "-afoo"],
                              "%s: file does not exist" %
                              test_support.TESTFN)
 
-    def test_file_irregular(self):
+    def test_filetype_notfile(self):
         os.mkdir(test_support.TESTFN)
         self.assertParseFail(["--file", test_support.TESTFN, "-afoo"],
                              "%s: not a regular file" %
                              test_support.TESTFN)
-        os.rmdir(test_support.TESTFN)
+
 
 class TestExtendAddActions(BaseTest):
     def setUp(self):
@@ -1003,7 +1060,7 @@
         STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",)
         TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",)
 
-        def take_action (self, action, dest, opt, value, values, parser):
+        def take_action(self, action, dest, opt, value, values, parser):
             if action == "extend":
                 lvalue = value.split(",")
                 values.ensure_value(dest, []).extend(lvalue)
@@ -1072,7 +1129,7 @@
                           callback=lambda: None, type="string",
                           help="foo")
 
-        expected_help = ("options:\n"
+        expected_help = ("Options:\n"
                          "  -t TEST, --test=TEST  foo\n")
         self.assertHelp(parser, expected_help)
 
@@ -1085,7 +1142,7 @@
                                dest="points", default=[])]
         self.parser = OptionParser(option_list=options)
 
-    def process_tuple (self, option, opt, value, parser_, len, type):
+    def process_tuple(self, option, opt, value, parser_, len, type):
         self.assertEqual(len, 3)
         self.assert_(type is int)
 
@@ -1110,7 +1167,7 @@
         self.parser = OptionParser(option_list=options)
 
     # Callback that meddles in rargs, largs
-    def process_n (self, option, opt, value, parser_):
+    def process_n(self, option, opt, value, parser_):
         # option is -3, -5, etc.
         nargs = int(opt[1:])
         rargs = parser_.rargs
@@ -1139,7 +1196,7 @@
                                callback=self.process_many, type="int")]
         self.parser = OptionParser(option_list=options)
 
-    def process_many (self, option, opt, value, parser_):
+    def process_many(self, option, opt, value, parser_):
         if opt == "-a":
             self.assertEqual(value, ("foo", "bar"))
         elif opt == "--apple":
@@ -1162,7 +1219,7 @@
         self.parser.add_option("--foo-bar", action="callback",
                                callback=self.check_abbrev)
 
-    def check_abbrev (self, option, opt, value, parser):
+    def check_abbrev(self, option, opt, value, parser):
         self.assertEqual(opt, "--foo-bar")
 
     def test_abbrev_callback_expansion(self):
@@ -1177,7 +1234,7 @@
         self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
                                                option_list=options)
 
-    def variable_args (self, option, opt, value, parser):
+    def variable_args(self, option, opt, value, parser):
         self.assert_(value is None)
         done = 0
         value = []
@@ -1229,7 +1286,7 @@
         self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
                                                option_list=options)
 
-    def show_version (self, option, opt, value, parser):
+    def show_version(self, option, opt, value, parser):
         parser.values.show_version = 1
 
 class TestConflict(ConflictBase):
@@ -1280,7 +1337,7 @@
 
     def test_conflict_resolve_help(self):
         self.assertOutput(["-h"], """\
-options:
+Options:
   --verbose      increment verbosity
   -h, --help     show this help message and exit
   -v, --version  show version
@@ -1319,7 +1376,7 @@
 
     def test_conflict_override_help(self):
         self.assertOutput(["-h"], """\
-options:
+Options:
   -h, --help     show this help message and exit
   -n, --dry-run  dry run mode
 """)
@@ -1332,9 +1389,9 @@
 # -- Other testing. ----------------------------------------------------
 
 _expected_help_basic = """\
-usage: bar.py [options]
+Usage: bar.py [options]
 
-options:
+Options:
   -a APPLE           throw APPLEs at basket
   -b NUM, --boo=NUM  shout "boo!" NUM times (in order to frighten away all the
                      evil spirits that cause trouble and mayhem)
@@ -1343,9 +1400,9 @@
 """
 
 _expected_help_long_opts_first = """\
-usage: bar.py [options]
+Usage: bar.py [options]
 
-options:
+Options:
   -a APPLE           throw APPLEs at basket
   --boo=NUM, -b NUM  shout "boo!" NUM times (in order to frighten away all the
                      evil spirits that cause trouble and mayhem)
@@ -1358,7 +1415,7 @@
 =====
   bar.py [options]
 
-options
+Options
 =======
 -a APPLE           throw APPLEs at basket
 --boo=NUM, -b NUM  shout "boo!" NUM times (in order to frighten away all the
@@ -1368,9 +1425,9 @@
 """
 
 _expected_help_short_lines = """\
-usage: bar.py [options]
+Usage: bar.py [options]
 
-options:
+Options:
   -a APPLE           throw APPLEs at basket
   -b NUM, --boo=NUM  shout "boo!" NUM times (in order to
                      frighten away all the evil spirits
@@ -1382,15 +1439,8 @@
 
 class TestHelp(BaseTest):
     def setUp(self):
-        self.orig_columns = os.environ.get('COLUMNS')
         self.parser = self.make_parser(80)
 
-    def tearDown(self):
-        if self.orig_columns is None:
-            del os.environ['COLUMNS']
-        else:
-            os.environ['COLUMNS'] = self.orig_columns
-
     def make_parser(self, columns):
         options = [
             make_option("-a", type="string", dest='a',
@@ -1419,7 +1469,7 @@
         self.assertHelpEquals(_expected_help_basic)
 
     def test_help_old_usage(self):
-        self.parser.set_usage("usage: %prog [options]")
+        self.parser.set_usage("Usage: %prog [options]")
         self.assertHelpEquals(_expected_help_basic)
 
     def test_help_long_opts_first(self):
@@ -1449,13 +1499,13 @@
         group.add_option("-g", action="store_true", help="Group option.")
         self.parser.add_option_group(group)
 
-        self.assertHelpEquals("""\
-usage: bar.py [options]
+        expect = """\
+Usage: bar.py [options]
 
 This is the program description for bar.py.  bar.py has an option group as
 well as single options.
 
-options:
+Options:
   -a APPLE           throw APPLEs at basket
   -b NUM, --boo=NUM  shout "boo!" NUM times (in order to frighten away all the
                      evil spirits that cause trouble and mayhem)
@@ -1467,9 +1517,12 @@
     that some of them bite.
 
     -g               Group option.
-""")
+"""
 
+        self.assertHelpEquals(expect)
 
+        self.parser.epilog = "Please report bugs to /dev/null."
+        self.assertHelpEquals(expect + "\nPlease report bugs to /dev/null.\n")
 
 
 class TestMatchAbbrev(BaseTest):
@@ -1490,6 +1543,43 @@
             BadOptionError, "ambiguous option: --f (%s?)" % possibilities)
 
 
+class TestParseNumber(BaseTest):
+    def setUp(self):
+        self.parser = InterceptingOptionParser()
+        self.parser.add_option("-n", type=int)
+        self.parser.add_option("-l", type=long)
+
+    def test_parse_num_fail(self):
+        self.assertRaises(
+            _parse_num, ("", int), {},
+            ValueError,
+            re.compile(r"invalid literal for int().*: '?'?"))
+        self.assertRaises(
+            _parse_num, ("0xOoops", long), {},
+            ValueError,
+            re.compile(r"invalid literal for long().*: '?0xOoops'?"))
+
+    def test_parse_num_ok(self):
+        self.assertEqual(_parse_num("0", int), 0)
+        self.assertEqual(_parse_num("0x10", int), 16)
+        self.assertEqual(_parse_num("0XA", long), 10L)
+        self.assertEqual(_parse_num("010", long), 8L)
+        self.assertEqual(_parse_num("0b11", int), 3)
+        self.assertEqual(_parse_num("0b", long), 0L)
+
+    def test_numeric_options(self):
+        self.assertParseOK(["-n", "42", "-l", "0x20"],
+                           { "n": 42, "l": 0x20 }, [])
+        self.assertParseOK(["-n", "0b0101", "-l010"],
+                           { "n": 5, "l": 8 }, [])
+        self.assertParseFail(["-n008"],
+                             "option -n: invalid integer value: '008'")
+        self.assertParseFail(["-l0b0123"],
+                             "option -l: invalid long integer value: '0b0123'")
+        self.assertParseFail(["-l", "0x12x"],
+                             "option -l: invalid long integer value: '0x12x'")
+
+
 def _testclasses():
     mod = sys.modules[__name__]
     return [getattr(mod, name) for name in dir(mod) if name.startswith('Test')]

Modified: python/trunk/Misc/NEWS
==============================================================================
--- python/trunk/Misc/NEWS	(original)
+++ python/trunk/Misc/NEWS	Sun Apr 23 05:47:58 2006
@@ -86,6 +86,11 @@
 Library
 -------
 
+- Updated optparse module to Optik 1.5.1 (allow numeric constants in
+  hex, octal, or binary; add ``append_const`` action; keep going if
+  gettext cannot be imported; added ``OptionParser.destroy()`` method;
+  added ``epilog`` for better help generation).
+
 - Bug #1473760: ``tempfile.TemporaryFile()`` could hang on Windows, when
   called from a thread spawned as a side effect of importing a module.
 


More information about the Python-checkins mailing list