Kaydet (Commit) ab05edc0 authored tarafından Greg Ward's avatar Greg Ward

Update optparse to Optik 1.5.1.

üst cdd43280
...@@ -35,9 +35,9 @@ With these few lines of code, users of your script can now do the ...@@ -35,9 +35,9 @@ With these few lines of code, users of your script can now do the
\end{verbatim} \end{verbatim}
As it parses the command line, \code{optparse} sets attributes of the 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 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 \code{options.verbose} will be \code{False}. \code{optparse} supports both long
and short options, allows short options to be merged together, and and short options, allows short options to be merged together, and
allows options to be associated with their arguments in a variety of allows options to be associated with their arguments in a variety of
...@@ -100,8 +100,8 @@ options; the traditional \UNIX{} syntax is a hyphen (``-'') followed by a ...@@ -100,8 +100,8 @@ options; the traditional \UNIX{} syntax is a hyphen (``-'') followed by a
single letter, e.g. \code{"-x"} or \code{"-F"}. Also, traditional \UNIX{} single letter, e.g. \code{"-x"} or \code{"-F"}. Also, traditional \UNIX{}
syntax allows multiple options to be merged into a single argument, syntax allows multiple options to be merged into a single argument,
e.g. \code{"-x -F"} is equivalent to \code{"-xF"}. The GNU project e.g. \code{"-x -F"} is equivalent to \code{"-xF"}. The GNU project
introduced \code{"{--}"} followed by a series of hyphen-separated words, introduced \code{"-{}-"} followed by a series of hyphen-separated words,
e.g. \code{"{--}file"} or \code{"{--}dry-run"}. These are the only two option e.g. \code{"-{}-file"} or \code{"-{}-dry-run"}. These are the only two option
syntaxes provided by \module{optparse}. syntaxes provided by \module{optparse}.
Some other option syntaxes that the world has seen include: Some other option syntaxes that the world has seen include:
...@@ -170,7 +170,7 @@ For example, consider this hypothetical command-line: ...@@ -170,7 +170,7 @@ For example, consider this hypothetical command-line:
prog -v --report /tmp/report.txt foo bar prog -v --report /tmp/report.txt foo bar
\end{verbatim} \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 \longprogramopt{report} takes one argument, \code{"/tmp/report.txt"} is an option
argument. \code{"foo"} and \code{"bar"} are positional arguments. argument. \code{"foo"} and \code{"bar"} are positional arguments.
...@@ -287,12 +287,12 @@ but that's rarely necessary: by default it uses \code{sys.argv{[}1:]}.) ...@@ -287,12 +287,12 @@ but that's rarely necessary: by default it uses \code{sys.argv{[}1:]}.)
\method{parse{\_}args()} returns two values: \method{parse{\_}args()} returns two values:
\begin{itemize} \begin{itemize}
\item {} \item {}
\var{options}, an object containing values for all of your options{---}e.g. if \code{"-{}-file"} takes a single string argument, then \code{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.file} will be the filename supplied by the user, or
\code{None} if the user did not supply that option \code{None} if the user did not supply that option
\item {} \item {}
\var{args}, the list of positional arguments leftover after parsing \code{args}, the list of positional arguments leftover after parsing
options options
\end{itemize} \end{itemize}
...@@ -309,7 +309,7 @@ command line. There is a fixed set of actions hard-coded into \module{optparse} ...@@ -309,7 +309,7 @@ command line. There is a fixed set of actions hard-coded into \module{optparse}
adding new actions is an advanced topic covered in section~\ref{optparse-extending}, Extending \module{optparse}. 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 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 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}. If you don't specify an option action, \module{optparse} defaults to \code{store}.
...@@ -333,8 +333,8 @@ args = ["-f", "foo.txt"] ...@@ -333,8 +333,8 @@ args = ["-f", "foo.txt"]
\end{verbatim} \end{verbatim}
When \module{optparse} sees the option string \code{"-f"}, it consumes the next 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, argument, \code{"foo.txt"}, and stores it in \code{options.filename}. So,
after this call to \method{parse{\_}args()}, \var{options.filename} is after this call to \method{parse{\_}args()}, \code{options.filename} is
\code{"foo.txt"}. \code{"foo.txt"}.
Some other option types supported by \module{optparse} are \code{int} and \code{float}. Some other option types supported by \module{optparse} are \code{int} and \code{float}.
...@@ -379,7 +379,7 @@ types is covered in section~\ref{optparse-extending}, Extending \module{optparse ...@@ -379,7 +379,7 @@ types is covered in section~\ref{optparse-extending}, Extending \module{optparse
Flag options{---}set a variable to true or false when a particular option 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 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 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} \begin{verbatim}
parser.add_option("-v", action="store_true", dest="verbose") parser.add_option("-v", action="store_true", dest="verbose")
parser.add_option("-q", action="store_false", dest="verbose") parser.add_option("-q", action="store_false", dest="verbose")
...@@ -421,7 +421,7 @@ want more control. \module{optparse} lets you supply a default value for each ...@@ -421,7 +421,7 @@ want more control. \module{optparse} lets you supply a default value for each
destination, which is assigned before the command line is parsed. destination, which is assigned before the command line is parsed.
First, consider the verbose/quiet example. If we want \module{optparse} to set 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} \begin{verbatim}
parser.add_option("-v", action="store_true", dest="verbose", default=True) parser.add_option("-v", action="store_true", dest="verbose", default=True)
parser.add_option("-q", action="store_false", dest="verbose") parser.add_option("-q", action="store_false", dest="verbose")
...@@ -441,7 +441,7 @@ parser.add_option("-v", action="store_true", dest="verbose", default=False) ...@@ -441,7 +441,7 @@ parser.add_option("-v", action="store_true", dest="verbose", default=False)
parser.add_option("-q", action="store_false", dest="verbose", default=True) parser.add_option("-q", action="store_false", dest="verbose", default=True)
\end{verbatim} \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 default value supplied for any particular destination is the one that
counts. counts.
...@@ -566,7 +566,7 @@ argument to OptionParser: ...@@ -566,7 +566,7 @@ argument to OptionParser:
parser = OptionParser(usage="%prog [-f] [-q]", version="%prog 1.0") parser = OptionParser(usage="%prog [-f] [-q]", version="%prog 1.0")
\end{verbatim} \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 from that, \code{version} can contain anything you like. When you supply
it, \module{optparse} automatically adds a \code{"-{}-version"} option to your parser. it, \module{optparse} automatically adds a \code{"-{}-version"} option to your parser.
If it encounters this option on the command line, it expands your If it encounters this option on the command line, it expands your
...@@ -580,14 +580,14 @@ foo 1.0 ...@@ -580,14 +580,14 @@ foo 1.0
\end{verbatim} \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: There are two broad classes of errors that \module{optparse} has to worry about:
programmer errors and user errors. Programmer errors are usually 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 unknown option attributes, missing option attributes, etc. These are
dealt with in the usual way: raise an exception (either 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 Handling user errors is much more important, since they are guaranteed
to happen no matter how stable your code is. \module{optparse} can automatically to happen no matter how stable your code is. \module{optparse} can automatically
...@@ -659,12 +659,66 @@ def main(): ...@@ -659,12 +659,66 @@ def main():
if __name__ == "__main__": if __name__ == "__main__":
main() main()
\end{verbatim} \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}} \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}} \subsubsection{Populating the parser\label{optparse-populating-parser}}
There are several ways to populate the parser with options. The There are several ways to populate the parser with options. The
...@@ -708,38 +762,34 @@ strings, e.g. \programopt{-f} and \longprogramopt{file}. You can ...@@ -708,38 +762,34 @@ strings, e.g. \programopt{-f} and \longprogramopt{file}. You can
specify any number of short or long option strings, but you must specify specify any number of short or long option strings, but you must specify
at least one overall option string. at least one overall option string.
The canonical way to create an Option instance is by calling The canonical way to create an Option instance is with the
\function{make{\_}option()}, so that is what will be shown here. However, the \method{add{\_}option()} method of \class{OptionParser}:
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:
\begin{verbatim} \begin{verbatim}
make_option(opt_str, ..., attr=value, ...) parser.add_option(opt_str[, ...], attr=value, ...)
parser.add_option(opt_str, ..., attr=value, ...)
\end{verbatim} \end{verbatim}
To define an option with only a short option string: To define an option with only a short option string:
\begin{verbatim} \begin{verbatim}
make_option("-f", attr=value, ...) parser.add_option("-f", attr=value, ...)
\end{verbatim} \end{verbatim}
And to define an option with only a long option string: And to define an option with only a long option string:
\begin{verbatim} \begin{verbatim}
make_option("--foo", attr=value, ...) parser.add_option("--foo", attr=value, ...)
\end{verbatim} \end{verbatim}
The \code{attr=value} keyword arguments define option attributes, The keyword arguments define attributes of the new Option object. The
i.e. attributes of the Option object. The most important option most important option attribute is \member{action}, and it largely determines
attribute is \member{action}, and it largely determines what other attributes which other attributes are relevant or required. If you pass irrelevant
are relevant or required. If you pass irrelevant option attributes, or option attributes, or fail to pass required ones, \module{optparse} raises an
fail to pass required ones, \module{optparse} raises an OptionError exception OptionError exception explaining your mistake.
explaining your mistake.
An options's \emph{action} determines what \module{optparse} does when it encounters An options's \emph{action} determines what \module{optparse} does when it encounters this
this option on the command-line. The actions hard-coded into \module{optparse} are: option on the command-line. The standard option actions hard-coded into
\module{optparse} are:
\begin{description} \begin{description}
\item[\code{store}] \item[\code{store}]
store this option's argument {[}default] store this option's argument (default)
\item[\code{store{\_}const}] \item[\code{store{\_}const}]
store a constant value store a constant value
\item[\code{store{\_}true}] \item[\code{store{\_}true}]
...@@ -748,6 +798,8 @@ store a true value ...@@ -748,6 +798,8 @@ store a true value
store a false value store a false value
\item[\code{append}] \item[\code{append}]
append this option's argument to a list append this option's argument to a list
\item[\code{append{\_}const}]
append a constant value to a list
\item[\code{count}] \item[\code{count}]
increment a counter by one increment a counter by one
\item[\code{callback}] \item[\code{callback}]
...@@ -762,24 +814,25 @@ action, you may also supply \member{type} and \member{dest} option attributes; s ...@@ -762,24 +814,25 @@ action, you may also supply \member{type} and \member{dest} option attributes; s
below.) below.)
As you can see, most actions involve storing or updating a value As you can see, most actions involve storing or updating a value
somewhere. \module{optparse} always creates an instance of \code{optparse.Values} somewhere. \module{optparse} always creates a special object for this,
specifically for this purpose; we refer to this instance as \var{options}. conventionally called \code{options} (it happens to be an instance of
Option arguments (and various other values) are stored as attributes of \code{optparse.Values}). Option arguments (and various other values) are
this object, according to the \member{dest} (destination) option attribute. stored as attributes of this object, according to the \member{dest}
(destination) option attribute.
For example, when you call For example, when you call
\begin{verbatim} \begin{verbatim}
parser.parse_args() parser.parse_args()
\end{verbatim} \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} \begin{verbatim}
options = Values() options = Values()
\end{verbatim} \end{verbatim}
If one of the options in this parser is defined with If one of the options in this parser is defined with
\begin{verbatim} \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} \end{verbatim}
and the command-line being parsed includes any of the following: and the command-line being parsed includes any of the following:
...@@ -790,8 +843,7 @@ and the command-line being parsed includes any of the following: ...@@ -790,8 +843,7 @@ and the command-line being parsed includes any of the following:
--file foo --file foo
\end{verbatim} \end{verbatim}
then \module{optparse}, on seeing the \programopt{-f} or \longprogramopt{file} option, will do the then \module{optparse}, on seeing this option, will do the equivalent of
equivalent of
\begin{verbatim} \begin{verbatim}
options.filename = "foo" options.filename = "foo"
\end{verbatim} \end{verbatim}
...@@ -911,6 +963,13 @@ If, a little later on, \code{"-{}-tracks=4"} is seen, it does: ...@@ -911,6 +963,13 @@ If, a little later on, \code{"-{}-tracks=4"} is seen, it does:
options.tracks.append(int("4")) options.tracks.append(int("4"))
\end{verbatim} \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 {} \item {}
\code{count} {[}relevant: \member{dest}] \code{count} {[}relevant: \member{dest}]
...@@ -939,14 +998,9 @@ options.verbosity += 1 ...@@ -939,14 +998,9 @@ options.verbosity += 1
\code{callback} {[}required: \code{callback}; \code{callback} {[}required: \code{callback};
relevant: \member{type}, \code{nargs}, \code{callback{\_}args}, \code{callback{\_}kwargs}] relevant: \member{type}, \code{nargs}, \code{callback{\_}args}, \code{callback{\_}kwargs}]
Call the function specified by \code{callback}. The signature of Call the function specified by \code{callback}, which is called as
this function should be
\begin{verbatim} \begin{verbatim}
func(option : Option, func(option, opt_str, value, parser, *args, **kwargs)
opt : string,
value : any,
parser : OptionParser,
*args, **kwargs)
\end{verbatim} \end{verbatim}
See section~\ref{optparse-option-callbacks}, Option Callbacks for more detail. See section~\ref{optparse-option-callbacks}, Option Callbacks for more detail.
...@@ -956,7 +1010,7 @@ See section~\ref{optparse-option-callbacks}, Option Callbacks for more detail. ...@@ -956,7 +1010,7 @@ See section~\ref{optparse-option-callbacks}, Option Callbacks for more detail.
Prints a complete help message for all the options in the Prints a complete help message for all the options in the
current option parser. The help message is constructed from 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. the \member{help} string passed to every option.
If no \member{help} string is supplied for an option, it will still be If no \member{help} string is supplied for an option, it will still be
...@@ -1007,6 +1061,87 @@ constructor. As with \member{help} options, you will rarely create ...@@ -1007,6 +1061,87 @@ constructor. As with \member{help} options, you will rarely create
\end{itemize} \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}} \subsubsection{Standard option types\label{optparse-standard-option-types}}
\module{optparse} has six built-in option types: \code{string}, \code{int}, \code{long}, \module{optparse} has six built-in option types: \code{string}, \code{int}, \code{long},
...@@ -1017,22 +1152,74 @@ Arguments to string options are not checked or converted in any way: the ...@@ -1017,22 +1152,74 @@ Arguments to string options are not checked or converted in any way: the
text on the command line is stored in the destination (or passed to the text on the command line is stored in the destination (or passed to the
callback) as-is. callback) as-is.
Integer arguments are passed to \code{int()} to convert them to Python Integer arguments (type \code{int} or \code{long}) are parsed as follows:
integers. If \code{int()} fails, so will \module{optparse}, although with a more \begin{quote}
useful error message. (Internally, \module{optparse} raises \begin{itemize}
\exception{OptionValueError}; OptionParser catches this exception higher \item {}
up and terminates your program with a useful error message.) 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.
Likewise, \code{float} arguments are passed to \code{float()} for conversion, \code{float} and \code{complex} option arguments are converted directly with
\code{long} arguments to \code{long()}, and \code{complex} arguments to \code{float()} and \code{complex()}, with similar error-handling.
\code{complex()}. Apart from that, they are handled identically to integer
arguments.
\code{choice} options are a subtype of \code{string} options. The \code{choices} \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 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 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}} \subsubsection{Querying and manipulating your option parser\label{optparse-querying-manipulating-option-parser}}
...@@ -1050,9 +1237,8 @@ Returns the Option instance with the option string \code{opt{\_}str}, or ...@@ -1050,9 +1237,8 @@ Returns the Option instance with the option string \code{opt{\_}str}, or
If the OptionParser has an option corresponding to \code{opt{\_}str}, If the OptionParser has an option corresponding to \code{opt{\_}str},
that option is removed. If that option provided any other that option is removed. If that option provided any other
option strings, all of those option strings become invalid. option strings, all of those option strings become invalid.
If \code{opt{\_}str} does not occur in any option belonging to this If \code{opt{\_}str} does not occur in any option belonging to this
OptionParser, raises \exception{ValueError}. OptionParser, raises ValueError.
\end{description} \end{description}
...@@ -1074,20 +1260,20 @@ options. If it finds any, it invokes the current conflict-handling ...@@ -1074,20 +1260,20 @@ options. If it finds any, it invokes the current conflict-handling
mechanism. You can set the conflict-handling mechanism either in the mechanism. You can set the conflict-handling mechanism either in the
constructor: constructor:
\begin{verbatim} \begin{verbatim}
parser = OptionParser(..., conflict_handler="...") parser = OptionParser(..., conflict_handler=handler)
\end{verbatim} \end{verbatim}
or with a separate call: or with a separate call:
\begin{verbatim} \begin{verbatim}
parser.set_conflict_handler("...") parser.set_conflict_handler(handler)
\end{verbatim} \end{verbatim}
The available conflict-handling mechanisms are: The available conflict handlers are:
\begin{quote} \begin{quote}
\begin{description} \begin{description}
\item[\code{error} (default)] \item[\code{error} (default)]
assume option conflicts are a programming error and raise assume option conflicts are a programming error and raise
\exception{OptionConflictError} OptionConflictError
\item[\code{resolve}] \item[\code{resolve}]
resolve option conflicts intelligently (see below) resolve option conflicts intelligently (see below)
\end{description} \end{description}
...@@ -1131,7 +1317,78 @@ options: ...@@ -1131,7 +1317,78 @@ options:
-n, --noisy be noisy -n, --noisy be noisy
--dry-run new dry-run option --dry-run new dry-run option
\end{verbatim} \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}} \subsection{Option Callbacks\label{optparse-option-callbacks}}
...@@ -1234,7 +1491,7 @@ its instance attributes: ...@@ -1234,7 +1491,7 @@ its instance attributes:
the current list of leftover arguments, ie. arguments that have the current list of leftover arguments, ie. arguments that have
been consumed but are neither options nor option arguments. been consumed but are neither options nor option arguments.
Feel free to modify \code{parser.largs}, e.g. by adding more 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()}.) return value of \method{parse{\_}args()}.)
\item[\code{parser.rargs}] \item[\code{parser.rargs}]
the current list of remaining arguments, ie. with \code{opt{\_}str} and the current list of remaining arguments, ie. with \code{opt{\_}str} and
...@@ -1260,7 +1517,7 @@ is a dictionary of arbitrary keyword arguments supplied via ...@@ -1260,7 +1517,7 @@ is a dictionary of arbitrary keyword arguments supplied via
\subsubsection{Raising errors in a callback\label{optparse-raising-errors-in-callback}} \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 problems with the option or its argument(s). \module{optparse} catches this and
terminates the program, printing the error message you supply to terminates the program, printing the error message you supply to
stderr. Your message should be clear, concise, accurate, and mention stderr. Your message should be clear, concise, accurate, and mention
......
...@@ -16,7 +16,7 @@ For support, use the optik-users@lists.sourceforge.net mailing list ...@@ -16,7 +16,7 @@ For support, use the optik-users@lists.sourceforge.net mailing list
# Python developers: please do not make changes to this file, since # Python developers: please do not make changes to this file, since
# it is automatically generated from the Optik source code. # it is automatically generated from the Optik source code.
__version__ = "1.5a2" __version__ = "1.5.1"
__all__ = ['Option', __all__ = ['Option',
'SUPPRESS_HELP', 'SUPPRESS_HELP',
...@@ -35,8 +35,8 @@ __all__ = ['Option', ...@@ -35,8 +35,8 @@ __all__ = ['Option',
'BadOptionError'] 'BadOptionError']
__copyright__ = """ __copyright__ = """
Copyright (c) 2001-2004 Gregory P. Ward. All rights reserved. Copyright (c) 2001-2006 Gregory P. Ward. All rights reserved.
Copyright (c) 2002-2004 Python Software Foundation. All rights reserved. Copyright (c) 2002-2006 Python Software Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are modification, are permitted provided that the following conditions are
...@@ -67,21 +67,26 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ...@@ -67,21 +67,26 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
""" """
import sys, os import sys, os
import types
import textwrap import textwrap
try:
from gettext import gettext as _
except ImportError:
_ = lambda arg: arg
def _repr(self): def _repr(self):
return "<%s at 0x%x: %s>" % (self.__class__.__name__, id(self), self) return "<%s at 0x%x: %s>" % (self.__class__.__name__, id(self), self)
# This file was generated from: # This file was generated from:
# Id: option_parser.py 421 2004-10-26 00:45:16Z greg # Id: option_parser.py 509 2006-04-20 00:58:24Z gward
# Id: option.py 422 2004-10-26 00:53:47Z greg # Id: option.py 509 2006-04-20 00:58:24Z gward
# Id: help.py 367 2004-07-24 23:21:21Z gward # Id: help.py 509 2006-04-20 00:58:24Z gward
# Id: errors.py 367 2004-07-24 23:21:21Z 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): class OptParseError (Exception):
def __init__(self, msg): def __init__(self, msg):
...@@ -120,8 +125,25 @@ class OptionValueError (OptParseError): ...@@ -120,8 +125,25 @@ class OptionValueError (OptParseError):
class BadOptionError (OptParseError): 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: class HelpFormatter:
...@@ -223,15 +245,30 @@ class HelpFormatter: ...@@ -223,15 +245,30 @@ class HelpFormatter:
def format_heading(self, heading): def format_heading(self, heading):
raise NotImplementedError, "subclasses must implement" raise NotImplementedError, "subclasses must implement"
def format_description(self, description): def _format_text(self, text):
if not description: """
return "" Format a paragraph of free-form text for inclusion in the
desc_width = self.width - self.current_indent help output at the current indentation level.
"""
text_width = self.width - self.current_indent
indent = " "*self.current_indent indent = " "*self.current_indent
return textwrap.fill(description, return textwrap.fill(text,
desc_width, text_width,
initial_indent=indent, 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): def expand_default(self, option):
if self.parser is None or not self.default_tag: if self.parser is None or not self.default_tag:
...@@ -328,7 +365,7 @@ class IndentedHelpFormatter (HelpFormatter): ...@@ -328,7 +365,7 @@ class IndentedHelpFormatter (HelpFormatter):
self, indent_increment, max_help_position, width, short_first) self, indent_increment, max_help_position, width, short_first)
def format_usage(self, usage): def format_usage(self, usage):
return _("usage: %s\n") % usage return _("Usage: %s\n") % usage
def format_heading(self, heading): def format_heading(self, heading):
return "%*s%s:\n" % (self.current_indent, "", heading) return "%*s%s:\n" % (self.current_indent, "", heading)
...@@ -353,8 +390,27 @@ class TitledHelpFormatter (HelpFormatter): ...@@ -353,8 +390,27 @@ class TitledHelpFormatter (HelpFormatter):
return "%s\n%s\n" % (heading, "=-"[self.level] * len(heading)) return "%s\n%s\n" % (heading, "=-"[self.level] * len(heading))
_builtin_cvt = { "int" : (int, _("integer")), def _parse_num(val, type):
"long" : (long, _("long integer")), 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")), "float" : (float, _("floating-point")),
"complex" : (complex, _("complex")) } "complex" : (complex, _("complex")) }
...@@ -422,6 +478,7 @@ class Option: ...@@ -422,6 +478,7 @@ class Option:
"store_true", "store_true",
"store_false", "store_false",
"append", "append",
"append_const",
"count", "count",
"callback", "callback",
"help", "help",
...@@ -435,6 +492,7 @@ class Option: ...@@ -435,6 +492,7 @@ class Option:
"store_true", "store_true",
"store_false", "store_false",
"append", "append",
"append_const",
"count") "count")
# The set of actions for which it makes sense to supply a value # The set of actions for which it makes sense to supply a value
...@@ -448,6 +506,10 @@ class Option: ...@@ -448,6 +506,10 @@ class Option:
ALWAYS_TYPED_ACTIONS = ("store", ALWAYS_TYPED_ACTIONS = ("store",
"append") "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 # The set of known types for option parsers. Again, listed here for
# constructor argument validation. # constructor argument validation.
TYPES = ("string", "int", "long", "float", "complex", "choice") TYPES = ("string", "int", "long", "float", "complex", "choice")
...@@ -572,9 +634,17 @@ class Option: ...@@ -572,9 +634,17 @@ class Option:
# No type given? "string" is the most sensible default. # No type given? "string" is the most sensible default.
self.type = "string" self.type = "string"
else: else:
# Allow type objects as an alternative to their names. # Allow type objects or builtin type conversion functions
if type(self.type) is type: # (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__ self.type = self.type.__name__
if self.type == "str": if self.type == "str":
self.type = "string" self.type = "string"
...@@ -589,7 +659,7 @@ class Option: ...@@ -589,7 +659,7 @@ class Option:
if self.choices is None: if self.choices is None:
raise OptionError( raise OptionError(
"must supply a list of choices for type 'choice'", self) "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( raise OptionError(
"choices must be a list of strings ('%s' supplied)" "choices must be a list of strings ('%s' supplied)"
% str(type(self.choices)).split("'")[1], self) % str(type(self.choices)).split("'")[1], self)
...@@ -613,7 +683,7 @@ class Option: ...@@ -613,7 +683,7 @@ class Option:
self.dest = self._short_opts[0][1] self.dest = self._short_opts[0][1]
def _check_const(self): 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( raise OptionError(
"'const' must not be supplied for action %r" % self.action, "'const' must not be supplied for action %r" % self.action,
self) self)
...@@ -633,12 +703,12 @@ class Option: ...@@ -633,12 +703,12 @@ class Option:
raise OptionError( raise OptionError(
"callback not callable: %r" % self.callback, self) "callback not callable: %r" % self.callback, self)
if (self.callback_args is not None and 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( raise OptionError(
"callback_args, if supplied, must be a tuple: not %r" "callback_args, if supplied, must be a tuple: not %r"
% self.callback_args, self) % self.callback_args, self)
if (self.callback_kwargs is not None and 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( raise OptionError(
"callback_kwargs, if supplied, must be a dict: not %r" "callback_kwargs, if supplied, must be a dict: not %r"
% self.callback_kwargs, self) % self.callback_kwargs, self)
...@@ -720,6 +790,8 @@ class Option: ...@@ -720,6 +790,8 @@ class Option:
setattr(values, dest, False) setattr(values, dest, False)
elif action == "append": elif action == "append":
values.ensure_value(dest, []).append(value) values.ensure_value(dest, []).append(value)
elif action == "append_const":
values.ensure_value(dest, []).append(self.const)
elif action == "count": elif action == "count":
setattr(values, dest, values.ensure_value(dest, 0) + 1) setattr(values, dest, values.ensure_value(dest, 0) + 1)
elif action == "callback": elif action == "callback":
...@@ -748,11 +820,9 @@ try: ...@@ -748,11 +820,9 @@ try:
True, False True, False
except NameError: except NameError:
(True, False) = (1, 0) (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: class Values:
...@@ -766,16 +836,13 @@ class Values: ...@@ -766,16 +836,13 @@ class Values:
__repr__ = _repr __repr__ = _repr
def __eq__(self, other): def __cmp__(self, other):
if isinstance(other, Values): if isinstance(other, Values):
return self.__dict__ == other.__dict__ return cmp(self.__dict__, other.__dict__)
elif isinstance(other, dict): elif isinstance(other, types.DictType):
return self.__dict__ == other return cmp(self.__dict__, other)
else: else:
return False return -1
def __ne__(self, other):
return not (self == other)
def _update_careful(self, dict): def _update_careful(self, dict):
""" """
...@@ -893,6 +960,13 @@ class OptionContainer: ...@@ -893,6 +960,13 @@ class OptionContainer:
return self.description return self.description
def destroy(self):
"""see OptionParser.destroy()."""
del self._short_opt
del self._long_opt
del self.defaults
# -- Option-adding methods ----------------------------------------- # -- Option-adding methods -----------------------------------------
def _check_conflict(self, option): def _check_conflict(self, option):
...@@ -926,7 +1000,7 @@ class OptionContainer: ...@@ -926,7 +1000,7 @@ class OptionContainer:
"""add_option(Option) """add_option(Option)
add_option(opt_str, ..., kwarg=val, ...) 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) option = self.option_class(*args, **kwargs)
elif len(args) == 1 and not kwargs: elif len(args) == 1 and not kwargs:
option = args[0] option = args[0]
...@@ -1018,6 +1092,11 @@ class OptionGroup (OptionContainer): ...@@ -1018,6 +1092,11 @@ class OptionGroup (OptionContainer):
def set_title(self, title): def set_title(self, title):
self.title = title self.title = title
def destroy(self):
"""see OptionParser.destroy()."""
OptionContainer.destroy(self)
del self.option_list
# -- Help-formatting methods --------------------------------------- # -- Help-formatting methods ---------------------------------------
def format_help(self, formatter): def format_help(self, formatter):
...@@ -1044,6 +1123,8 @@ class OptionParser (OptionContainer): ...@@ -1044,6 +1123,8 @@ class OptionParser (OptionContainer):
prog : string prog : string
the name of the current program (to override the name of the current program (to override
os.path.basename(sys.argv[0])). os.path.basename(sys.argv[0])).
epilog : string
paragraph of help text to print after option help
option_groups : [OptionGroup] option_groups : [OptionGroup]
list of option groups in this parser (option groups are list of option groups in this parser (option groups are
...@@ -1102,7 +1183,8 @@ class OptionParser (OptionContainer): ...@@ -1102,7 +1183,8 @@ class OptionParser (OptionContainer):
description=None, description=None,
formatter=None, formatter=None,
add_help_option=True, add_help_option=True,
prog=None): prog=None,
epilog=None):
OptionContainer.__init__( OptionContainer.__init__(
self, option_class, conflict_handler, description) self, option_class, conflict_handler, description)
self.set_usage(usage) self.set_usage(usage)
...@@ -1114,6 +1196,7 @@ class OptionParser (OptionContainer): ...@@ -1114,6 +1196,7 @@ class OptionParser (OptionContainer):
formatter = IndentedHelpFormatter() formatter = IndentedHelpFormatter()
self.formatter = formatter self.formatter = formatter
self.formatter.set_parser(self) self.formatter.set_parser(self)
self.epilog = epilog
# Populate the option list; initial sources are the # Populate the option list; initial sources are the
# standard_option_list class attribute, the 'option_list' # standard_option_list class attribute, the 'option_list'
...@@ -1124,6 +1207,22 @@ class OptionParser (OptionContainer): ...@@ -1124,6 +1207,22 @@ class OptionParser (OptionContainer):
self._init_parsing_state() 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 ----------------------------------------------- # -- Private methods -----------------------------------------------
# (used by our or OptionContainer's constructor) # (used by our or OptionContainer's constructor)
...@@ -1167,7 +1266,7 @@ class OptionParser (OptionContainer): ...@@ -1167,7 +1266,7 @@ class OptionParser (OptionContainer):
elif usage is SUPPRESS_USAGE: elif usage is SUPPRESS_USAGE:
self.usage = None self.usage = None
# For backwards compatibility with Optik 1.3 and earlier. # For backwards compatibility with Optik 1.3 and earlier.
elif usage.startswith("usage:" + " "): elif usage.lower().startswith("usage: "):
self.usage = usage[7:] self.usage = usage[7:]
else: else:
self.usage = usage self.usage = usage
...@@ -1201,7 +1300,7 @@ class OptionParser (OptionContainer): ...@@ -1201,7 +1300,7 @@ class OptionParser (OptionContainer):
defaults = self.defaults.copy() defaults = self.defaults.copy()
for option in self._get_all_options(): for option in self._get_all_options():
default = defaults.get(option.dest) default = defaults.get(option.dest)
if isinstance(default, basestring): if isbasestring(default):
opt_str = option.get_opt_string() opt_str = option.get_opt_string()
defaults[option.dest] = option.check_value(opt_str, default) defaults[option.dest] = option.check_value(opt_str, default)
...@@ -1212,7 +1311,7 @@ class OptionParser (OptionContainer): ...@@ -1212,7 +1311,7 @@ class OptionParser (OptionContainer):
def add_option_group(self, *args, **kwargs): def add_option_group(self, *args, **kwargs):
# XXX lots of overlap with OptionContainer.add_option() # 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) group = OptionGroup(self, *args, **kwargs)
elif len(args) == 1 and not kwargs: elif len(args) == 1 and not kwargs:
group = args[0] group = args[0]
...@@ -1276,7 +1375,7 @@ class OptionParser (OptionContainer): ...@@ -1276,7 +1375,7 @@ class OptionParser (OptionContainer):
try: try:
stop = self._process_args(largs, rargs, values) stop = self._process_args(largs, rargs, values)
except (BadOptionError, OptionValueError), err: except (BadOptionError, OptionValueError), err:
self.error(err.msg) self.error(str(err))
args = largs + rargs args = largs + rargs
return self.check_values(values, args) return self.check_values(values, args)
...@@ -1401,7 +1500,7 @@ class OptionParser (OptionContainer): ...@@ -1401,7 +1500,7 @@ class OptionParser (OptionContainer):
i += 1 # we have consumed a character i += 1 # we have consumed a character
if not option: if not option:
self.error(_("no such option: %s") % opt) raise BadOptionError(opt)
if option.takes_value(): if option.takes_value():
# Any characters left in arg? Pretend they're the # Any characters left in arg? Pretend they're the
# next arg, and stop consuming characters of arg. # next arg, and stop consuming characters of arg.
...@@ -1501,7 +1600,7 @@ class OptionParser (OptionContainer): ...@@ -1501,7 +1600,7 @@ class OptionParser (OptionContainer):
formatter = self.formatter formatter = self.formatter
formatter.store_option_strings(self) formatter.store_option_strings(self)
result = [] result = []
result.append(formatter.format_heading(_("options"))) result.append(formatter.format_heading(_("Options")))
formatter.indent() formatter.indent()
if self.option_list: if self.option_list:
result.append(OptionContainer.format_option_help(self, formatter)) result.append(OptionContainer.format_option_help(self, formatter))
...@@ -1513,6 +1612,9 @@ class OptionParser (OptionContainer): ...@@ -1513,6 +1612,9 @@ class OptionParser (OptionContainer):
# Drop the last "\n", or the header if no options or option groups: # Drop the last "\n", or the header if no options or option groups:
return "".join(result[:-1]) return "".join(result[:-1])
def format_epilog(self, formatter):
return formatter.format_epilog(self.epilog)
def format_help(self, formatter=None): def format_help(self, formatter=None):
if formatter is None: if formatter is None:
formatter = self.formatter formatter = self.formatter
...@@ -1522,6 +1624,7 @@ class OptionParser (OptionContainer): ...@@ -1522,6 +1624,7 @@ class OptionParser (OptionContainer):
if self.description: if self.description:
result.append(self.format_description(formatter) + "\n") result.append(self.format_description(formatter) + "\n")
result.append(self.format_option_help(formatter)) result.append(self.format_option_help(formatter))
result.append(self.format_epilog(formatter))
return "".join(result) return "".join(result)
def print_help(self, file=None): def print_help(self, file=None):
...@@ -1555,11 +1658,10 @@ def _match_abbrev(s, wordmap): ...@@ -1555,11 +1658,10 @@ def _match_abbrev(s, wordmap):
if len(possibilities) == 1: if len(possibilities) == 1:
return possibilities[0] return possibilities[0]
elif not possibilities: elif not possibilities:
raise BadOptionError(_("no such option: %s") % s) raise BadOptionError(s)
else: else:
# More than one possible completion: ambiguous prefix. # More than one possible completion: ambiguous prefix.
raise BadOptionError(_("ambiguous option: %s (%s?)") raise AmbiguousOptionError(s, possibilities)
% (s, ", ".join(possibilities)))
# Some day, there might be many Option classes. As of Optik 1.3, the # Some day, there might be many Option classes. As of Optik 1.3, the
......
...@@ -10,17 +10,22 @@ ...@@ -10,17 +10,22 @@
import sys import sys
import os import os
import re
import copy import copy
import types
import unittest import unittest
from cStringIO import StringIO from cStringIO import StringIO
from pprint import pprint from pprint import pprint
from test import test_support from test import test_support
from optparse import make_option, Option, IndentedHelpFormatter, \ from optparse import make_option, Option, IndentedHelpFormatter, \
TitledHelpFormatter, OptionParser, OptionContainer, OptionGroup, \ TitledHelpFormatter, OptionParser, OptionContainer, OptionGroup, \
SUPPRESS_HELP, SUPPRESS_USAGE, OptionError, OptionConflictError, \ 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. # Do the right thing with boolean values for all known Python versions.
try: try:
...@@ -28,6 +33,7 @@ try: ...@@ -28,6 +33,7 @@ try:
except NameError: except NameError:
(True, False) = (1, 0) (True, False) = (1, 0)
retype = type(re.compile(''))
class InterceptedError(Exception): class InterceptedError(Exception):
def __init__(self, def __init__(self,
...@@ -96,7 +102,8 @@ Args were %(args)s.""" % locals ()) ...@@ -96,7 +102,8 @@ Args were %(args)s.""" % locals ())
args -- positional arguments to `func` args -- positional arguments to `func`
kwargs -- keyword arguments to `func` kwargs -- keyword arguments to `func`
expected_exception -- exception that should be raised 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. Returns the exception raised for further testing.
""" """
...@@ -109,14 +116,23 @@ Args were %(args)s.""" % locals ()) ...@@ -109,14 +116,23 @@ Args were %(args)s.""" % locals ())
func(*args, **kwargs) func(*args, **kwargs)
except expected_exception, err: except expected_exception, err:
actual_message = str(err) actual_message = str(err)
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, self.assertEqual(actual_message,
expected_message, expected_message,
"""\ """\
expected exception message: expected exception message:
'''%(expected_message)s''' '''%s'''
actual exception message: actual exception message:
'''%(actual_message)s''' '''%s'''
""" % locals()) """ % (expected_message, actual_message))
return err return err
else: else:
...@@ -157,7 +173,9 @@ and kwargs %(kwargs)r ...@@ -157,7 +173,9 @@ and kwargs %(kwargs)r
sys.stdout = save_stdout sys.stdout = save_stdout
except InterceptedError, err: 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_status, expected_status)
self.assertEqual(err.exit_message, expected_error) self.assertEqual(err.exit_message, expected_error)
else: else:
...@@ -366,6 +384,23 @@ class TestOptionParser(BaseTest): ...@@ -366,6 +384,23 @@ class TestOptionParser(BaseTest):
self.assertRaises(self.parser.remove_option, ('foo',), None, self.assertRaises(self.parser.remove_option, ('foo',), None,
ValueError, "no such option 'foo'") 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): class TestOptionValues(BaseTest):
def setUp(self): def setUp(self):
pass pass
...@@ -391,13 +426,21 @@ class TestTypeAliases(BaseTest): ...@@ -391,13 +426,21 @@ class TestTypeAliases(BaseTest):
def setUp(self): def setUp(self):
self.parser = OptionParser() self.parser = OptionParser()
def test_type_aliases(self): def test_str_aliases_string(self):
self.parser.add_option("-x", type=int) 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("-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") 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("-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. # Custom type for testing processing of default values.
...@@ -487,13 +530,13 @@ class TestProgName(BaseTest): ...@@ -487,13 +530,13 @@ class TestProgName(BaseTest):
save_argv = sys.argv[:] save_argv = sys.argv[:]
try: try:
sys.argv[0] = os.path.join("foo", "bar", "baz.py") sys.argv[0] = os.path.join("foo", "bar", "baz.py")
parser = OptionParser("usage: %prog ...", version="%prog 1.2") parser = OptionParser("%prog ...", version="%prog 1.2")
expected_usage = "usage: baz.py ...\n" expected_usage = "Usage: baz.py ...\n"
self.assertUsage(parser, expected_usage) self.assertUsage(parser, expected_usage)
self.assertVersion(parser, "baz.py 1.2") self.assertVersion(parser, "baz.py 1.2")
self.assertHelp(parser, self.assertHelp(parser,
expected_usage + "\n" + expected_usage + "\n" +
"options:\n" "Options:\n"
" --version show program's version number and exit\n" " --version show program's version number and exit\n"
" -h, --help show this help message and exit\n") " -h, --help show this help message and exit\n")
finally: finally:
...@@ -505,7 +548,7 @@ class TestProgName(BaseTest): ...@@ -505,7 +548,7 @@ class TestProgName(BaseTest):
usage="%prog arg arg") usage="%prog arg arg")
parser.remove_option("-h") parser.remove_option("-h")
parser.remove_option("--version") parser.remove_option("--version")
expected_usage = "usage: thingy arg arg\n" expected_usage = "Usage: thingy arg arg\n"
self.assertUsage(parser, expected_usage) self.assertUsage(parser, expected_usage)
self.assertVersion(parser, "thingy 0.1") self.assertVersion(parser, "thingy 0.1")
self.assertHelp(parser, expected_usage + "\n") self.assertHelp(parser, expected_usage + "\n")
...@@ -515,9 +558,9 @@ class TestExpandDefaults(BaseTest): ...@@ -515,9 +558,9 @@ class TestExpandDefaults(BaseTest):
def setUp(self): def setUp(self):
self.parser = OptionParser(prog="test") self.parser = OptionParser(prog="test")
self.help_prefix = """\ self.help_prefix = """\
usage: test [options] Usage: test [options]
options: Options:
-h, --help show this help message and exit -h, --help show this help message and exit
""" """
self.file_help = "read from FILE [default: %default]" self.file_help = "read from FILE [default: %default]"
...@@ -699,13 +742,16 @@ class TestStandard(BaseTest): ...@@ -699,13 +742,16 @@ class TestStandard(BaseTest):
self.assertParseOK(["-a", "--", "foo", "bar"], self.assertParseOK(["-a", "--", "foo", "bar"],
{'a': "--", 'boo': None, 'foo': None}, {'a': "--", 'boo': None, 'foo': None},
["foo", "bar"]), ["foo", "bar"]),
self.assertParseOK(["-a", "--", "--foo", "bar"],
{'a': "--", 'boo': None, 'foo': ["bar"]},
[]),
def test_short_option_joined_and_separator(self): def test_short_option_joined_and_separator(self):
self.assertParseOK(["-ab", "--", "--foo", "bar"], self.assertParseOK(["-ab", "--", "--foo", "bar"],
{'a': "b", 'boo': None, 'foo': None}, {'a': "b", 'boo': None, 'foo': None},
["--foo", "bar"]), ["--foo", "bar"]),
def test_invalid_option_becomes_positional_arg(self): def test_hyphen_becomes_positional_arg(self):
self.assertParseOK(["-ab", "-", "--foo", "bar"], self.assertParseOK(["-ab", "-", "--foo", "bar"],
{'a': "b", 'boo': None, 'foo': ["bar"]}, {'a': "b", 'boo': None, 'foo': ["bar"]},
["-"]) ["-"])
...@@ -870,6 +916,8 @@ class TestMultipleArgsAppend(BaseTest): ...@@ -870,6 +916,8 @@ class TestMultipleArgsAppend(BaseTest):
type="float", dest="point") type="float", dest="point")
self.parser.add_option("-f", "--foo", action="append", nargs=2, self.parser.add_option("-f", "--foo", action="append", nargs=2,
type="int", dest="foo") type="int", dest="foo")
self.parser.add_option("-z", "--zero", action="append_const",
dest="foo", const=(0, 0))
def test_nargs_append(self): def test_nargs_append(self):
self.assertParseOK(["-f", "4", "-3", "blah", "--foo", "1", "666"], self.assertParseOK(["-f", "4", "-3", "blah", "--foo", "1", "666"],
...@@ -885,6 +933,11 @@ class TestMultipleArgsAppend(BaseTest): ...@@ -885,6 +933,11 @@ class TestMultipleArgsAppend(BaseTest):
{'point': None, 'foo':[(3, 4)]}, {'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): class TestVersion(BaseTest):
def test_version(self): def test_version(self):
self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE, self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
...@@ -960,8 +1013,14 @@ class TestExtendAddTypes(BaseTest): ...@@ -960,8 +1013,14 @@ class TestExtendAddTypes(BaseTest):
self.parser.add_option("-a", None, type="string", dest="a") self.parser.add_option("-a", None, type="string", dest="a")
self.parser.add_option("-f", "--file", type="file", dest="file") 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): class MyOption (Option):
def check_file (option, opt, value): def check_file(option, opt, value):
if not os.path.exists(value): if not os.path.exists(value):
raise OptionValueError("%s: file does not exist" % value) raise OptionValueError("%s: file does not exist" % value)
elif not os.path.isfile(value): elif not os.path.isfile(value):
...@@ -972,25 +1031,23 @@ class TestExtendAddTypes(BaseTest): ...@@ -972,25 +1031,23 @@ class TestExtendAddTypes(BaseTest):
TYPE_CHECKER = copy.copy(Option.TYPE_CHECKER) TYPE_CHECKER = copy.copy(Option.TYPE_CHECKER)
TYPE_CHECKER["file"] = check_file TYPE_CHECKER["file"] = check_file
def test_extend_file(self): def test_filetype_ok(self):
open(test_support.TESTFN, "w").close() open(test_support.TESTFN, "w").close()
self.assertParseOK(["--file", test_support.TESTFN, "-afoo"], self.assertParseOK(["--file", test_support.TESTFN, "-afoo"],
{'file': test_support.TESTFN, 'a': 'foo'}, {'file': test_support.TESTFN, 'a': 'foo'},
[]) [])
os.unlink(test_support.TESTFN) def test_filetype_noexist(self):
def test_extend_file_nonexistent(self):
self.assertParseFail(["--file", test_support.TESTFN, "-afoo"], self.assertParseFail(["--file", test_support.TESTFN, "-afoo"],
"%s: file does not exist" % "%s: file does not exist" %
test_support.TESTFN) test_support.TESTFN)
def test_file_irregular(self): def test_filetype_notfile(self):
os.mkdir(test_support.TESTFN) os.mkdir(test_support.TESTFN)
self.assertParseFail(["--file", test_support.TESTFN, "-afoo"], self.assertParseFail(["--file", test_support.TESTFN, "-afoo"],
"%s: not a regular file" % "%s: not a regular file" %
test_support.TESTFN) test_support.TESTFN)
os.rmdir(test_support.TESTFN)
class TestExtendAddActions(BaseTest): class TestExtendAddActions(BaseTest):
def setUp(self): def setUp(self):
...@@ -1003,7 +1060,7 @@ class TestExtendAddActions(BaseTest): ...@@ -1003,7 +1060,7 @@ class TestExtendAddActions(BaseTest):
STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",) STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",)
TYPED_ACTIONS = Option.TYPED_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": if action == "extend":
lvalue = value.split(",") lvalue = value.split(",")
values.ensure_value(dest, []).extend(lvalue) values.ensure_value(dest, []).extend(lvalue)
...@@ -1072,7 +1129,7 @@ class TestCallback(BaseTest): ...@@ -1072,7 +1129,7 @@ class TestCallback(BaseTest):
callback=lambda: None, type="string", callback=lambda: None, type="string",
help="foo") help="foo")
expected_help = ("options:\n" expected_help = ("Options:\n"
" -t TEST, --test=TEST foo\n") " -t TEST, --test=TEST foo\n")
self.assertHelp(parser, expected_help) self.assertHelp(parser, expected_help)
...@@ -1085,7 +1142,7 @@ class TestCallbackExtraArgs(BaseTest): ...@@ -1085,7 +1142,7 @@ class TestCallbackExtraArgs(BaseTest):
dest="points", default=[])] dest="points", default=[])]
self.parser = OptionParser(option_list=options) 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.assertEqual(len, 3)
self.assert_(type is int) self.assert_(type is int)
...@@ -1110,7 +1167,7 @@ class TestCallbackMeddleArgs(BaseTest): ...@@ -1110,7 +1167,7 @@ class TestCallbackMeddleArgs(BaseTest):
self.parser = OptionParser(option_list=options) self.parser = OptionParser(option_list=options)
# Callback that meddles in rargs, largs # 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. # option is -3, -5, etc.
nargs = int(opt[1:]) nargs = int(opt[1:])
rargs = parser_.rargs rargs = parser_.rargs
...@@ -1139,7 +1196,7 @@ class TestCallbackManyArgs(BaseTest): ...@@ -1139,7 +1196,7 @@ class TestCallbackManyArgs(BaseTest):
callback=self.process_many, type="int")] callback=self.process_many, type="int")]
self.parser = OptionParser(option_list=options) 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": if opt == "-a":
self.assertEqual(value, ("foo", "bar")) self.assertEqual(value, ("foo", "bar"))
elif opt == "--apple": elif opt == "--apple":
...@@ -1162,7 +1219,7 @@ class TestCallbackCheckAbbrev(BaseTest): ...@@ -1162,7 +1219,7 @@ class TestCallbackCheckAbbrev(BaseTest):
self.parser.add_option("--foo-bar", action="callback", self.parser.add_option("--foo-bar", action="callback",
callback=self.check_abbrev) 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") self.assertEqual(opt, "--foo-bar")
def test_abbrev_callback_expansion(self): def test_abbrev_callback_expansion(self):
...@@ -1177,7 +1234,7 @@ class TestCallbackVarArgs(BaseTest): ...@@ -1177,7 +1234,7 @@ class TestCallbackVarArgs(BaseTest):
self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE, self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
option_list=options) option_list=options)
def variable_args (self, option, opt, value, parser): def variable_args(self, option, opt, value, parser):
self.assert_(value is None) self.assert_(value is None)
done = 0 done = 0
value = [] value = []
...@@ -1229,7 +1286,7 @@ class ConflictBase(BaseTest): ...@@ -1229,7 +1286,7 @@ class ConflictBase(BaseTest):
self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE, self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
option_list=options) option_list=options)
def show_version (self, option, opt, value, parser): def show_version(self, option, opt, value, parser):
parser.values.show_version = 1 parser.values.show_version = 1
class TestConflict(ConflictBase): class TestConflict(ConflictBase):
...@@ -1280,7 +1337,7 @@ class TestConflictResolve(ConflictBase): ...@@ -1280,7 +1337,7 @@ class TestConflictResolve(ConflictBase):
def test_conflict_resolve_help(self): def test_conflict_resolve_help(self):
self.assertOutput(["-h"], """\ self.assertOutput(["-h"], """\
options: Options:
--verbose increment verbosity --verbose increment verbosity
-h, --help show this help message and exit -h, --help show this help message and exit
-v, --version show version -v, --version show version
...@@ -1319,7 +1376,7 @@ class TestConflictOverride(BaseTest): ...@@ -1319,7 +1376,7 @@ class TestConflictOverride(BaseTest):
def test_conflict_override_help(self): def test_conflict_override_help(self):
self.assertOutput(["-h"], """\ self.assertOutput(["-h"], """\
options: Options:
-h, --help show this help message and exit -h, --help show this help message and exit
-n, --dry-run dry run mode -n, --dry-run dry run mode
""") """)
...@@ -1332,9 +1389,9 @@ options: ...@@ -1332,9 +1389,9 @@ options:
# -- Other testing. ---------------------------------------------------- # -- Other testing. ----------------------------------------------------
_expected_help_basic = """\ _expected_help_basic = """\
usage: bar.py [options] Usage: bar.py [options]
options: Options:
-a APPLE throw APPLEs at basket -a APPLE throw APPLEs at basket
-b NUM, --boo=NUM shout "boo!" NUM times (in order to frighten away all the -b NUM, --boo=NUM shout "boo!" NUM times (in order to frighten away all the
evil spirits that cause trouble and mayhem) evil spirits that cause trouble and mayhem)
...@@ -1343,9 +1400,9 @@ options: ...@@ -1343,9 +1400,9 @@ options:
""" """
_expected_help_long_opts_first = """\ _expected_help_long_opts_first = """\
usage: bar.py [options] Usage: bar.py [options]
options: Options:
-a APPLE throw APPLEs at basket -a APPLE throw APPLEs at basket
--boo=NUM, -b NUM shout "boo!" NUM times (in order to frighten away all the --boo=NUM, -b NUM shout "boo!" NUM times (in order to frighten away all the
evil spirits that cause trouble and mayhem) evil spirits that cause trouble and mayhem)
...@@ -1358,7 +1415,7 @@ Usage ...@@ -1358,7 +1415,7 @@ Usage
===== =====
bar.py [options] bar.py [options]
options Options
======= =======
-a APPLE throw APPLEs at basket -a APPLE throw APPLEs at basket
--boo=NUM, -b NUM shout "boo!" NUM times (in order to frighten away all the --boo=NUM, -b NUM shout "boo!" NUM times (in order to frighten away all the
...@@ -1368,9 +1425,9 @@ options ...@@ -1368,9 +1425,9 @@ options
""" """
_expected_help_short_lines = """\ _expected_help_short_lines = """\
usage: bar.py [options] Usage: bar.py [options]
options: Options:
-a APPLE throw APPLEs at basket -a APPLE throw APPLEs at basket
-b NUM, --boo=NUM shout "boo!" NUM times (in order to -b NUM, --boo=NUM shout "boo!" NUM times (in order to
frighten away all the evil spirits frighten away all the evil spirits
...@@ -1382,15 +1439,8 @@ options: ...@@ -1382,15 +1439,8 @@ options:
class TestHelp(BaseTest): class TestHelp(BaseTest):
def setUp(self): def setUp(self):
self.orig_columns = os.environ.get('COLUMNS')
self.parser = self.make_parser(80) 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): def make_parser(self, columns):
options = [ options = [
make_option("-a", type="string", dest='a', make_option("-a", type="string", dest='a',
...@@ -1419,7 +1469,7 @@ class TestHelp(BaseTest): ...@@ -1419,7 +1469,7 @@ class TestHelp(BaseTest):
self.assertHelpEquals(_expected_help_basic) self.assertHelpEquals(_expected_help_basic)
def test_help_old_usage(self): 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) self.assertHelpEquals(_expected_help_basic)
def test_help_long_opts_first(self): def test_help_long_opts_first(self):
...@@ -1449,13 +1499,13 @@ class TestHelp(BaseTest): ...@@ -1449,13 +1499,13 @@ class TestHelp(BaseTest):
group.add_option("-g", action="store_true", help="Group option.") group.add_option("-g", action="store_true", help="Group option.")
self.parser.add_option_group(group) self.parser.add_option_group(group)
self.assertHelpEquals("""\ expect = """\
usage: bar.py [options] Usage: bar.py [options]
This is the program description for bar.py. bar.py has an option group as This is the program description for bar.py. bar.py has an option group as
well as single options. well as single options.
options: Options:
-a APPLE throw APPLEs at basket -a APPLE throw APPLEs at basket
-b NUM, --boo=NUM shout "boo!" NUM times (in order to frighten away all the -b NUM, --boo=NUM shout "boo!" NUM times (in order to frighten away all the
evil spirits that cause trouble and mayhem) evil spirits that cause trouble and mayhem)
...@@ -1467,9 +1517,12 @@ options: ...@@ -1467,9 +1517,12 @@ options:
that some of them bite. that some of them bite.
-g Group option. -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): class TestMatchAbbrev(BaseTest):
...@@ -1490,6 +1543,43 @@ class TestMatchAbbrev(BaseTest): ...@@ -1490,6 +1543,43 @@ class TestMatchAbbrev(BaseTest):
BadOptionError, "ambiguous option: --f (%s?)" % possibilities) 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(): def _testclasses():
mod = sys.modules[__name__] mod = sys.modules[__name__]
return [getattr(mod, name) for name in dir(mod) if name.startswith('Test')] return [getattr(mod, name) for name in dir(mod) if name.startswith('Test')]
......
...@@ -86,6 +86,11 @@ Extension Modules ...@@ -86,6 +86,11 @@ Extension Modules
Library 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 - Bug #1473760: ``tempfile.TemporaryFile()`` could hang on Windows, when
called from a thread spawned as a side effect of importing a module. called from a thread spawned as a side effect of importing a module.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment