Index: Lib/optparse.py =================================================================== --- Lib/optparse.py (revision 79952) +++ Lib/optparse.py (working copy) @@ -393,8 +393,36 @@ def format_heading(self, heading): return "%s\n%s\n" % (heading, "=-"[self.level] * len(heading)) + +class OptionsOnlyHelpFormatter(HelpFormatter): + + def __init__(self, indent_increment=0, max_help_position=24, width=None, + short_first=0): + HelpFormatter.__init__(self, indent_increment, max_help_position, width, + short_first) + def format_option(self, option): + if option.takes_value(): + short_opts = ['%s=' % sopt for sopt in option._short_opts] + long_opts = ['%s=' % lopt for lopt in option._long_opts] + else: + short_opts = option._short_opts + long_opts = option._long_opts + opts = ', '.join(short_opts + long_opts) + opts = "%*s%s\n" % (self.current_indent, "", opts) + return opts + + def format_usage(self, usage): + return '' + + def format_heading(self, heading): + return '' + + def format_description(self, description): + return '' + + def _parse_num(val, type): if val[:2].lower() == "0x": # hexadecimal radix = 16 @@ -487,6 +515,7 @@ "count", "callback", "help", + "interface", "version") # The set of actions that involve storing a value somewhere; @@ -807,6 +836,9 @@ elif action == "help": parser.print_help() parser.exit() + elif action == 'interface': + parser.print_interface() + parser.exit() elif action == "version": parser.print_version() parser.exit() @@ -1068,9 +1100,13 @@ def format_help(self, formatter): result = [] if self.description: - result.append(self.format_description(formatter)) + description = self.format_description(formatter) + if description: + result.append(description) if self.option_list: - result.append(self.format_option_help(formatter)) + option_help = self.format_option_help(formatter) + if option_help: + result.append(option_help) return "\n".join(result) @@ -1232,13 +1268,18 @@ self.add_option("-h", "--help", action="help", help=_("show this help message and exit")) + + def _add_interface(self): + self.add_option("--help-options", action="interface", + help=_("show interface of this program")) def _add_version_option(self): self.add_option("--version", action="version", help=_("show program's version number and exit")) - def _populate_option_list(self, option_list, add_help=True): + def _populate_option_list(self, option_list, add_help=True, + add_interface=True): if self.standard_option_list: self.add_options(self.standard_option_list) if option_list: @@ -1247,6 +1288,8 @@ self._add_version_option() if add_help: self._add_help_option() + if add_interface: + self._add_interface() def _init_parsing_state(self): # These are set in parse_args() for the convenience of callbacks. @@ -1633,7 +1676,7 @@ result.append(self.format_option_help(formatter)) result.append(self.format_epilog(formatter)) return "".join(result) - + def print_help(self, file=None): """print_help(file : file = stdout) @@ -1643,7 +1686,21 @@ if file is None: file = sys.stdout file.write(self.format_help()) + + def format_interface(self): + formatter = OptionsOnlyHelpFormatter() + result = [] + if self.option_list: + result.append(OptionContainer.format_option_help(self, formatter)) + for group in self.option_groups: + result.append(group.format_help(formatter)) + return "".join(result) + def print_interface(self, file=None): + if file is None: + file = sys.stdout + file.write(self.format_interface()) + # class OptionParser Index: Lib/test/test_optparse.py =================================================================== --- Lib/test/test_optparse.py (revision 79952) +++ Lib/test/test_optparse.py (working copy) @@ -526,8 +526,9 @@ self.assertHelp(parser, expected_usage + "\n" + "Options:\n" - " --version show program's version number and exit\n" - " -h, --help show this help message and exit\n") + " --version show program's version number and exit\n" + " -h, --help show this help message and exit\n" + " --help-options show interface of this program\n") finally: sys.argv[:] = save_argv @@ -537,6 +538,7 @@ usage="%prog arg arg") parser.remove_option("-h") parser.remove_option("--version") + parser.remove_option("--help-options") expected_usage = "Usage: thingy arg arg\n" self.assertUsage(parser, expected_usage) self.assertVersion(parser, "thingy 0.1") @@ -551,6 +553,7 @@ Options: -h, --help show this help message and exit + --help-options show interface of this program """ self.file_help = "read from FILE [default: %default]" self.expected_help_file = self.help_prefix + \ @@ -1113,6 +1116,7 @@ # format_help() doesn't crash. parser = OptionParser(usage=SUPPRESS_USAGE) parser.remove_option("-h") + parser.remove_option("--help-options") parser.add_option("-t", "--test", action="callback", callback=lambda: None, type="string", help="foo") @@ -1325,9 +1329,10 @@ def test_conflict_resolve_help(self): self.assertOutput(["-h"], """\ Options: - --verbose increment verbosity - -h, --help show this help message and exit - -v, --version show version + --verbose increment verbosity + -h, --help show this help message and exit + --help-options show interface of this program + -v, --version show version """) def test_conflict_resolve_short_opt(self): @@ -1364,8 +1369,9 @@ def test_conflict_override_help(self): self.assertOutput(["-h"], """\ Options: - -h, --help show this help message and exit - -n, --dry-run dry run mode + -h, --help show this help message and exit + --help-options show interface of this program + -n, --dry-run dry run mode """) def test_conflict_override_args(self): @@ -1384,6 +1390,7 @@ evil spirits that cause trouble and mayhem) --foo=FOO store FOO in the foo list for later fooing -h, --help show this help message and exit + --help-options show interface of this program """ _expected_help_long_opts_first = """\ @@ -1395,6 +1402,7 @@ evil spirits that cause trouble and mayhem) --foo=FOO store FOO in the foo list for later fooing --help, -h show this help message and exit + --help-options show interface of this program """ _expected_help_title_formatter = """\ @@ -1409,6 +1417,7 @@ evil spirits that cause trouble and mayhem) --foo=FOO store FOO in the foo list for later fooing --help, -h show this help message and exit +--help-options show interface of this program """ _expected_help_short_lines = """\ @@ -1422,9 +1431,12 @@ --foo=FOO store FOO in the foo list for later fooing -h, --help show this help message and exit + --help-options show interface of this program """ -class TestHelp(BaseTest): + +class BaseHelpTest(BaseTest): + def setUp(self): self.parser = self.make_parser(80) @@ -1448,6 +1460,9 @@ with support.EnvironmentVarGuard() as env: env['COLUMNS'] = str(columns) return InterceptingOptionParser(option_list=options) + + +class TestHelp(BaseHelpTest): def assertHelpEquals(self, expected_output): save_argv = sys.argv[:] @@ -1487,8 +1502,9 @@ self.parser.add_option("-a", action="store_true", help="ol\u00E9!") expect = """\ Options: - -h, --help show this help message and exit - -a ol\u00E9! + -h, --help show this help message and exit + --help-options show interface of this program + -a ol\u00E9! """ self.assertHelpEquals(expect) @@ -1499,7 +1515,8 @@ ol\u00E9! Options: - -h, --help show this help message and exit + -h, --help show this help message and exit + --help-options show interface of this program """ self.assertHelpEquals(expect) @@ -1527,6 +1544,7 @@ evil spirits that cause trouble and mayhem) --foo=FOO store FOO in the foo list for later fooing -h, --help show this help message and exit + --help-options show interface of this program Dangerous Options: Caution: use of these options is at your own risk. It is believed @@ -1539,8 +1557,49 @@ self.parser.epilog = "Please report bugs to /dev/null." self.assertHelpEquals(expect + "\nPlease report bugs to /dev/null.\n") + +class TestHelpOptions(BaseHelpTest): + def assertHelpOptionsEquals(self, expected_output): + save_argv = sys.argv[:] + try: + # Make optparse believe bar.py is being executed. + sys.argv[0] = os.path.join("foo", "bar.py") + self.assertOutput(["--help-options"], expected_output) + finally: + sys.argv[:] = save_argv + + def test_help_options_basic(self): + expect = """\ +-a= +-b=, --boo= +--foo= +-h, --help +--help-options +""" + self.assertHelpOptionsEquals(expect) + + def test_help_options_groups(self): + + group = OptionGroup( + self.parser, "Dangerous Options", + "Caution: use of these options is at your own risk. " + "It is believed that some of them bite.") + group.add_option("-g", action="store_true", help="Group option.") + self.parser.add_option_group(group) + + expect = """\ +-a= +-b=, --boo= +--foo= +-h, --help +--help-options +-g +""" + self.assertHelpOptionsEquals(expect) + + class TestMatchAbbrev(BaseTest): def test_match_abbrev(self): self.assertEqual(_match_abbrev("--f",